Skip to content

feat: shared/ui 공통 컴포넌트 3종 구현 (Indicator, OptionItem, NumberField) - #30

Open
thwjddlqslek wants to merge 9 commits into
developfrom
feat/issue-14
Open

feat: shared/ui 공통 컴포넌트 3종 구현 (Indicator, OptionItem, NumberField)#30
thwjddlqslek wants to merge 9 commits into
developfrom
feat/issue-14

Conversation

@thwjddlqslek

@thwjddlqslek thwjddlqslek commented Aug 10, 2026

Copy link
Copy Markdown
Member

Summary

src/shared/ui가 비어 있던 상태에서 Figma 기반 공통 컴포넌트 3종을 구현한다.
여기서 정한 폴더 구조·작성 방식이 이후 모든 공통 컴포넌트의 기준이 되므로
ADR-0001로 같이 고정했다.

Related Issues

PR Point (To Reviewer)

컴포넌트

Indicator — 온보딩 단계 진행 표시. 세그먼트가 컨테이너 폭을 균등 분할합니다.
role="progressbar" + aria-valuenow/min/max. label prop으로 스크린리더 텍스트 주입 가능.

<Indicator total={5} current={2} />
<Indicator total={5} current={2} label="온보딩 진행 단계" />

OptionItem — 원형 이미지 선택 아이템. <button type="button"> + aria-pressed.
alt가 이미지 대체 텍스트 겸 aria-label. 선택 상태는 부모가 소유, 나열 컨테이너는 쓰는 쪽(feature)에서 만듭니다.

<OptionItem imageSrc={src} alt="달리기" selected onClick={...} />

NumberField (Figma 명칭 "text field"에서 숫자 전용임을 명확히 하기 위해 변경) — 숫자 전용 단일 라인 입력 필드. suffix로 단위 표시, error prop으로 외부에서 에러 상태 제어. ghost span으로 value + suffix를 하나의 덩어리로 center 정렬.
너비는 부모 컨테이너를 따릅니다(w-full). onChange 내부에서 숫자 외 문자를 필터링해 붙여넣기·IME·드래그앤드롭 등 모든 입력 경로를 커버.

<NumberField
  value={height}
  suffix="cm"
  placeholder="160"
  maxLength={3}
  error={error}
  onChange={(e) => setHeight(e.target.value)}
  onBlur={() => setError(!/^\d{3}$/.test(height))}
/>

error 판단 시점은 blur. 컴포넌트는 UI만 담당하고 검증 로직은 사용처가 소유합니다.

리뷰 포인트

OptionItem의 hover / pressed / selected가 같은 색 오버레이를 공유합니다.
bg-accent-base/20 하나로 세 상태를 처리하고, selectedring-2 ring-accent-base가 추가됩니다.

className은 세 컴포넌트 모두 루트 엘리먼트로 갑니다.

Screenshot

스크린샷 2026-08-11 오전 11 49 17 스크린샷 2026-08-11 오전 11 48 59 스크린샷 2026-08-11 오전 11 48 34

ETC

  • docs/adr/0001-shared-ui-component-convention.md 신규 — 폴더 구조, default export + 배럴 재노출, forwardRef 미사용, rem 임의값 표기, convenience prop 기준
  • docs/design/design-system.md Figma ↔ 코드 대응표, CONTEXT.md 용어집에 3종 반영
  • 색상·타이포·spacing은 styles/tokens/*.css의 기존 토큰만 사용

thwjddlqslek and others added 4 commits August 11, 2026 01:02
폴더/파일 네이밍, 배럴 구조, default export + named 재노출, forwardRef 미사용,
rem 임의값 표기, convenience prop 기준을 고정한다. CONTEXT.md 용어집에도
Indicator, OptionItem, TextField를 추가한다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014h9xQjVqHusEmVuiNyVACt
온보딩 단계 진행 표시. 세그먼트가 컨테이너 폭을 균등 분할하고,
role="progressbar" + aria-valuenow/min/max로 진행 상태를 노출한다.
current=0은 아직 시작 전이라 아무 칸도 채우지 않는다.

Figma: 482:7011

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014h9xQjVqHusEmVuiNyVACt
원형 이미지 + 라벨 선택 아이템. <button type="button"> + aria-pressed이고,
선택 상태는 부모가 소유한다. 이미지는 장식이라 alt=""로 두고, imageSrc가
없으면 플레이스홀더를 보여준다. hover/pressed/selected가 같은 색 오버레이를
공유하고 selected만 테두리가 추가된다.

Figma: 452:5885

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014h9xQjVqHusEmVuiNyVACt
TextField는 코드 위치만 잡아두고 구현 예정으로 표기한다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014h9xQjVqHusEmVuiNyVACt
@thwjddlqslek thwjddlqslek linked an issue Aug 10, 2026 that may be closed by this pull request
3 tasks
@thwjddlqslek thwjddlqslek self-assigned this Aug 10, 2026
@vercel

vercel Bot commented Aug 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
aligner Ready Ready Preview Aug 11, 2026 4:14am

thwjddlqslek and others added 4 commits August 11, 2026 11:38
숫자 전용 입력 필드. suffix prop으로 단위(cm, kg 등) 표시,
error prop으로 외부에서 에러 상태 제어 (blur 시 판단은 사용처에서).
ghost span으로 value + suffix를 하나의 덩어리로 center 정렬.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
aria-label을 외부에서 주입할 수 있도록 label prop 추가 (기본값 "진행 단계").
gap/height 임의값을 디자인 토큰 기반 클래스로 교체.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
label prop을 alt로 변경해 이미지 대체 텍스트 의도를 명확히 함.
aria-label에도 alt를 사용해 접근성 보강.
라벨 텍스트 span 제거 — 이미지만 표시하는 구조로 단순화.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@thwjddlqslek thwjddlqslek changed the title feat: shared/ui 공통 컴포넌트 3종 구현 (Indicator, OptionItem, TextField) feat: shared/ui 공통 컴포넌트 3종 구현 (Indicator, OptionItem, NumberField) Aug 11, 2026
onKeyDown은 붙여넣기·IME·드래그앤드롭을 막지 못한다.
모든 입력 경로가 거치는 onChange에서 /\D/g replace로 처리.
외부 onChange prop은 필터링 후 그대로 호출된다.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
{Array.from({ length: total }, (_, index) => (
<span
key={index}
className={cn("h-1 flex-1", index < filled ? "bg-bg-inverse" : "bg-bg-muted")}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bg-mutedgray-97인데 디자인 스펙 보면 gray-96이어야 합니당

그리고 막대끼리 gap이 10px이라서 gap-5가 아니라 gap-2.5가 되어야 해요!!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

디자인 시안과 다른 부분이 있어 말씀 드립니당

  1. input 폰트는 title-1-emphasized입니다!
  2. suffix는 타이포가 typo-headline-regular이고, input과 suffix의 gap이 8px이라서 ml-3으로 해야합니다!
  3. 입력 박스만 봤을 때 높이가 82px이어야 하고, radius 값이 20px이어야 합니다!
  4. placeholder가 gray-95여야 하고, 아무 값도 입력되지 않았을 때 suffix도 같은 값이 되어야 합니다!
  5. input과 suffix가 중앙 정렬이 아닌 하단 정렬이 되어야 합니다!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: 공통 컴포넌트 3종 구현: Indicator, OptionItem, TextField

2 participants