diff --git a/src/components/profile/ProfileSection.tsx b/src/components/profile/ProfileSection.tsx
new file mode 100644
index 0000000..295c1c0
--- /dev/null
+++ b/src/components/profile/ProfileSection.tsx
@@ -0,0 +1,28 @@
+import type { ReactNode } from 'react'
+
+type ProfileSectionProps = {
+ title: string
+ icon?: ReactNode
+ children: ReactNode
+}
+
+export function ProfileSection({ title, icon, children }: ProfileSectionProps) {
+ const headingId = `${title.toLowerCase().replaceAll(' ', '-')}-heading`
+
+ return (
+
+
+ {icon}
+ {title}
+
+ {children}
+
+ )
+}
diff --git a/src/pages/ProfilePage.tsx b/src/pages/ProfilePage.tsx
index 593b507..41ec023 100644
--- a/src/pages/ProfilePage.tsx
+++ b/src/pages/ProfilePage.tsx
@@ -1,11 +1,12 @@
import { type Handle } from '@atcute/lexicons'
import { isHandle } from '@atcute/lexicons/syntax'
import { IconPin, IconThumbUp } from '@tabler/icons-react'
-import { type ReactNode, useEffect, useState } from 'react'
+import { useEffect, useState } from 'react'
import { useParams, useSearchParams } from 'react-router-dom'
import { ProfilePageSkeleton } from '../components/shared/PageSkeletons'
import { PageContainer } from '../components/layout/PageContainer'
import { ProfileHeader } from '../components/profile/ProfileHeader'
+import { ProfileSection } from '../components/profile/ProfileSection'
import { ProfileTabs } from '../components/profile/ProfileTabs'
import { RepoListItem } from '../components/repo/RepoListItem'
import { StringListItem } from '../components/string/StringListItem'
@@ -74,14 +75,10 @@ export function ProfilePage() {
{activeSection === 'overview' && (
-
-
-
- Pinned
-
+ }
+ >
{pinnedRepos?.length === 0 && No repos found.
}
{pinnedRepos && pinnedRepos.length > 0 && (
@@ -90,24 +87,20 @@ export function ProfilePage() {
))}
)}
-
-
-
-
-
- Recent Vouches
-
+
+
+ }
+ >
{recentVouches.length === 0 && No vouches yet.
}
{recentVouches.length > 0 && }
-
+
)}
{activeSection === 'repos' && (
-
+
{repos.items.length === 0 && No repositories found.
}
{repos.items.length > 0 && (
@@ -116,11 +109,11 @@ export function ProfilePage() {
))}
)}
-
+
)}
{activeSection === 'strings' && (
-
+
{strings.items.length === 0 && No strings found.
}
{strings.items.length > 0 && (
@@ -133,11 +126,11 @@ export function ProfilePage() {
))}
)}
-
+
)}
{activeSection === 'stars' && (
-
+
{starredRepos.length === 0 && No stars found.
}
{starredRepos.length > 0 && (
@@ -147,14 +140,14 @@ export function ProfilePage() {
))}
)}
-
+
)}
{activeSection === 'vouches' && (
-
+
{vouches.items.length === 0 && No vouches yet.
}
{vouches.items.length > 0 && }
-
+
)}
@@ -162,24 +155,6 @@ export function ProfilePage() {
)
}
-type ProfileCollectionProps = {
- title: string
- children: ReactNode
-}
-
-function ProfileCollection({ title, children }: ProfileCollectionProps) {
- const headingId = `${title.toLowerCase()}-heading`
-
- return (
-
-
- {title}
-
- {children}
-
- )
-}
-
function parseHandle(value: string | undefined): Handle | null {
if (value === undefined || !isHandle(value)) {
return null