Overview
Compare
Inspect
Login is an email/password-only Card (OAuth is wired at the adapter but unreachable from the UI), and onboarding is a value-props pager into a 6-step WizardShell (welcome / birthYear / consent-or-under-14-gate / displayName / playStyle / done) with self-reported birth year, no 본인인증, no region step, and the header-owns-back+progress / footer-owns-single-CTA nav law throughout.
route · apps/mobile/app/_layout.tsx AuthGate → login-screen.tsx (unauthenticated) · onboarding/src/onboarding-wizard-screen.tsx (needs_onboarding)
grounded in 16 source file(s)
packages/app/src/presentation/screens/auth/login-screen.tsxpackages/features/onboarding/src/onboarding-wizard-screen.tsxpackages/features/onboarding/src/onboarding-value-props.tsxpackages/features/onboarding/src/onboarding-step-consent.tsxpackages/features/onboarding/src/onboarding-step-birth-year.tsxpackages/features/onboarding/src/onboarding-step-under-14-gate.tsxpackages/features/onboarding/src/onboarding-step1-welcome.tsxpackages/features/onboarding/src/onboarding-step2-display-name.tsxpackages/features/onboarding/src/onboarding-step3-play-style.tsxpackages/features/onboarding/src/onboarding-step4-done.tsxpackages/ui/src/wizard-shell.tsxpackages/ui/src/selection-check.tsxpackages/ui/src/labeled-field.tsxpackages/app/src/domain/utils/consent-matrix.tspackages/app/src/config/i18n/ko/onboarding.tspackages/app/src/config/i18n/ko/common.ts
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
로그인 · 이메일만
Structure
Form
login-screen.tsx:83-159 — Logo(w180) + subtitle(emailLoginSubtitle) + Card with 2 LabeledField+StyledInput (email + secure password) + ActionButton action="primary" 로그인
No OAuth
NO social buttons render; useAuth().signInWithOAuth-style flow exists but is never called from UI — footer says "곧 추가돼요" (oauthComingSoon)
3
가치 소개 · 페이저
Structure
Pager
OnboardingValueProps (onboarding-value-props.tsx:234-303) — 3-card horizontal ScrollView pagingEnabled, top-right ActionButton action="cancel" 건너뛰기 (own row, NOT the bottom CTA bar), per-card pure-Tamagui illustration + t().onboarding.valueProp headline/subline
Dots
a 3-dot indicator (active = 2.5× width, $primary); bottom primary CTA 시작하기
4
출생연도 · 자기 신고
Structure
Field
a required LabeledField (size="lg", trailing *) + StyledInput number-pad maxLength 4 + a caption paragraph above it + a derived "만 N세" line below (onboarding-step-birth-year.tsx:76-105)
Gate
age < 14 → the consent step position is replaced by OnboardingStepUnder14Gate (ShieldAlert + 뒤로 가기 only, not depicted) — the under-14 flag also clamps maxNavigableStep so a user can't tap past consent to edit-around the gate
5
약관 동의 · 5개 항목
Structure
Rows
getRequiredConsentsForJurisdiction("KR") filtered showAtSignup = exactly 5: 이용약관[필수] · 개인정보 처리방침[필수] · 국외이전[필수] · 위치정보[선택] · 마케팅 푸시[선택] (consent-matrix.ts:43-100)
Row
SelectionCheck (shape="square", packages/ui/src/selection-check.tsx) — 24px, fills $primary + white check glyph when checked — next to ONE wrapping text run ("[필수]/[선택] " + label, uniform $text color, no per-required tint) + an inline "보기" link (onboarding-step-consent.tsx:122-165)
6
플레이 스타일 · 타일
Structure
Required field
the tile stack sits inside a required LabeledField (label "이용 방식", trailing *) — matches the wizard required-field law (canon/wizards.md) (onboarding-step3-play-style.tsx:41-72)
Tiles
3 full-width SelectionCard tiles (label + desc), selected = $primary border(2px) + $primarySubtle bg: 클럽/"정기 클럽 중심으로 활동해요" · 번개/"자유롭게 번개 경기를 즐겨요" · 둘 다/"클럽과 번개 모두 즐겨요"