Overview
Compare
Inspect
One DetailShell ("리더보드") over a 클럽 · 지역 · 전국 SegmentedTabs, each tab a FeedList with a top-3 LeaderboardPodium header, RankRows body, and a MyRankRow footer shown only when my rank falls past 50, with 지역 additionally prepending a "상위 N%" percentile hero.
route · apps/mobile/app/records/leaderboard.tsx → records/src/records-leaderboard-screen.tsx (leaderboard.tsx / ranking.tsx are legacy Redirects; lb/[clubId].tsx is a universal-link receiver, NOT this screen)
grounded in 5 source file(s)
packages/features/records/src/records-leaderboard-screen.tsxpackages/features/records/src/leaderboard-club-tab.tsxpackages/features/records/src/leaderboard-region-tab.tsxpackages/app/src/presentation/components/leaderboard-podium.tsxpackages/app/src/presentation/components/leaderboard-row.tsx
Spec
1
Foundations · 디자인 시스템
Spacing · 4px grid
$1 – $4
4 · 8 · 12 · 16 px
$5 – $10
20 · 24 · 32 · 40 · 48 · 64 px
Radius
$2 8 · $3 12 · $4 16 · $7 9999 (pill)
Color · Classic Grass (light)
Surface
$background #F8FBF9 · $card #FFFFFF · $surfaceTertiary #E5FAEA
Brand
$primary #006D37 · $primarySubtle #E5FAEA
Text
$text #0D100E · $textSecondary #4F5851 · $textTertiary #626C64
Border
$border #CAD4CC · $borderSubtle #DFE7E1
Status
$success #14804A · $warning #946200 · $error #B8332E
Badge intents
accent #E0F8F3/#007B6B · warning #FFF4D6/#946200 · error #FDECEC/#B8332E
Court
$courtClay #B84A2E · $courtHard #247BA0 · $courtGreen #006633
Typography · Pretendard
cardTitle · navTitle
16 / 24 · 600 · 17 / 22 · 600
cardBody · cardMeta
14 / 22 · 400 · 13 / 18 · 500
badge · micro
12 / 18 · 600 · 10 / 14 · 600
display Sm/Md/Lg/Xl
20/28 · 28/36 · 36/44 · 48/56 · 700
Primitives · @twomore/ui
Layout
YStack · XStack · Card (default/flat) · Well · Divider
Controls
Pressable · Badge · Icon · PillNav · MainTabShell · BottomCtaBand
Data viz
DateTile · CapacityRing · ProgressBar · AvatarStack · SegmentedDonutChart
Domain cards
SessionCard · ClubCard · VenueHero · SessionCompactRow · member row
Box sizes
AVATAR XS 28 · SM 32 · MD 40 · LG 44 · 2XL 88 · TOUCH_TARGET 44
Rationale
Every part is built from these — one 4px grid, the Pretendard type scale, the Classic-Grass palette, and the shared @twomore/ui primitives + domain cards.
2
DetailShell + 공유
Structure
Shell
DetailShell title=리더보드 scroll=false (records-leaderboard-screen.tsx:121)
Share
headerRight = Share2 HeaderIconButton — rendered ONLY when scope = 클럽 AND a primaryClub exists AND leaderboardEntries.length > 0 (L121-134)
3
범위 · SegmentedTabs
Structure
Tabs
SegmentedTabs<Scope> items=getScopeItems() preload="all" (records-leaderboard-screen.tsx:144-150) → PillNav + panes
Scopes
exactly 클럽 · 지역 · 전국 (leaderboard-helpers.ts:7,10-16) — 시즌 removed
4
포디움 · 상위 3
Structure
Podium
LeaderboardPodium (leaderboard-podium.tsx) — render order [2nd, 1st, 3rd], medals 🥇🥈🥉; a column now sizes to its OWN content (avatar + medal + block) plus a PODIUM_STEP spacer of 40/12/0px for 1st/2nd/3rd (fixed [100,128,88]px column heights were removed 2026-09-17 — QA 2026-09-16 found the old fixed heights shorter than the content, spilling the block upward over the section title above).
Card
PodiumCard — AvatarBubble 52 → medal displaySm → block ($card, top-rounded, $border ring if self) → medal-colored formatElo + "ELO" + EloTierBadge + name
5
순위 리스트 · 4위+
Structure
Row
LeaderboardRow/RankRow — rank # (w28 right, $textSecondary) + PlayerIdentityChip (showTier=false) + EloTierBadge + formatElo value
Self
isCurrentUser → borderLeft 3px + bold; the row appends its OWN <Divider/> (FeedList itemSeparator={null})
6
지역 · 상위 N% 히어로
Structure
Hero
Flat since 2026-09-17 (canvas + hero-identity laws) — RegionTab prepends a centered cardMeta region caption over a single-cell StatStrip (value = percentile, label = total-players count); the earlier Card + MapPin icon + displayXl number is retired (leaderboard-region-tab.tsx:140-160)
Empty
region-not-set → noRegionTitle + CTA 지역 설정하기 → editProfile
7
내 순위 · 50위 밖
Structure
Footer
MyRankRow (my-rank-row.tsx:20-38) — Card tone="flat" → PlayerIdentityChip("나") + cardTitle "내 순위 · N위"
Gate
rendered as the FeedList footer ONLY when computed rank > 50 (NOT scroll-pinned)
8
로딩 · 포디움 스켈레톤
Structure
Skeleton
a 3-block podium skeleton (leaderboard-skeleton.tsx) — one flat rounded rectangle per column at PODIUM_COLUMN_BASE_HEIGHT (196) plus each rank's PODIUM_STEP (so 2nd/1st/3rd render 208/236/196px, same stepped silhouette as the live podium) + 8 SkeletonRow — identical across all 3 tabs
9
비어있음 · 순위 없음
Structure
Empty
zero entries → notReadyTitle EmptyState; club-scope with no club → noClubTitle