diff --git a/src/components/repo/RepoIssues.tsx b/src/components/repo/RepoIssues.tsx
new file mode 100644
index 0000000..269883e
--- /dev/null
+++ b/src/components/repo/RepoIssues.tsx
@@ -0,0 +1,56 @@
+import type { Did } from '@atcute/lexicons'
+import { IconCircleDot, IconMessageCircle } from '@tabler/icons-react'
+import { useRepoIssues } from '../../hooks/useRepoIssues'
+import { SurfaceCard } from '../shared/SurfaceCard'
+
+type RepoIssuesProps = {
+ repoDid: Did
+}
+
+export function RepoIssues({ repoDid }: RepoIssuesProps) {
+ const { issues, error } = useRepoIssues(repoDid)
+
+ if (error) {
+ return
Could not load issues: {error.message}
+ }
+
+ if (issues === null) {
+ return Loading issues...
+ }
+
+ if (issues.items.length === 0) {
+ return No issues found.
+ }
+
+ return (
+
+ {issues.items.map((issue) => {
+ const isOpen = issue.state === 'open'
+
+ return (
+ -
+
+
+
+
+ {issue.state}
+
+
+
+
+ {issue.commentCount}
+
+
+
+ {issue.value.title}
+
+
+ )
+ })}
+
+ )
+}
diff --git a/src/hooks/useRepoIssues.ts b/src/hooks/useRepoIssues.ts
new file mode 100644
index 0000000..5193b9b
--- /dev/null
+++ b/src/hooks/useRepoIssues.ts
@@ -0,0 +1,25 @@
+import type { Did } from '@atcute/lexicons'
+import { useEffect, useState } from 'react'
+import { listIssues, type IssueList } from '../lib/tangled/repo'
+
+const INITIAL_ISSUE_LIMIT = 20
+
+export function useRepoIssues(repoDid: Did) {
+ const [issues, setIssues] = useState(null)
+ const [error, setError] = useState(null)
+
+ useEffect(() => {
+ async function loadIssues() {
+ setError(null)
+ try {
+ const result = await listIssues(repoDid, { limit: INITIAL_ISSUE_LIMIT })
+ setIssues(result)
+ } catch (caught) {
+ setError(caught instanceof Error ? caught : new Error('Unable to load issues.'))
+ }
+ }
+
+ void loadIssues()
+ }, [repoDid])
+ return { issues, error }
+}
diff --git a/src/lib/tangled/repo/index.ts b/src/lib/tangled/repo/index.ts
index db45660..470db78 100644
--- a/src/lib/tangled/repo/index.ts
+++ b/src/lib/tangled/repo/index.ts
@@ -7,8 +7,8 @@ export { getRepoByRepoDid } from './getRepoByRepoDid'
export { getRepoLog } from './getRepoLog'
export type { RepoLogOptions } from './getRepoLog'
export { getRepoTree } from './getRepoTree'
-export { listIssues } from './issues'
-export type { Issue, IssueList, ListIssuesOptions } from './issues'
+export { listIssues } from './listIssues'
+export type { Issue, IssueList, ListIssuesOptions } from './listIssues'
export { listRepos } from './listRepos'
export { getRepoName, getRepoRkey } from './types'
export type { Repo, RepoList } from './types'
diff --git a/src/lib/tangled/repo/issues.ts b/src/lib/tangled/repo/listIssues.ts
similarity index 100%
rename from src/lib/tangled/repo/issues.ts
rename to src/lib/tangled/repo/listIssues.ts
diff --git a/src/pages/RepoPage.tsx b/src/pages/RepoPage.tsx
index 074f48f..0299dfd 100644
--- a/src/pages/RepoPage.tsx
+++ b/src/pages/RepoPage.tsx
@@ -2,6 +2,7 @@ import { useEffect, useState } from 'react'
import { useParams, useSearchParams } from 'react-router-dom'
import { PageContainer } from '../components/layout/PageContainer'
import { ProfileByline } from '../components/profile/ProfileByline'
+import { RepoIssues } from '../components/repo/RepoIssues'
import { RepoReadme } from '../components/repo/RepoReadme'
import { parseRepoSection } from '../components/repo/repoSections'
import { RepoTabs } from '../components/repo/RepoTabs'
@@ -73,7 +74,9 @@ export function RepoPage() {
)}
- {activeSection === 'issues' && }
+ {activeSection === 'issues' && repo.value.repoDid !== undefined && (
+
+ )}
{activeSection === 'pulls' && }
{activeSection === 'pipelines' && }