Groo Design

공통 가이드

공유 토큰만 쓰는 컴포넌트 규칙 — DESIGN.md 의 Components 절

이 파일(DESIGN.md)은 brand-agnostic 공유 baseline이라 컴포넌트 스펙은 brand 파일(DESIGN.hr.md / DESIGN.desk.md)에 작성합니다 — primary 등 brand 토큰을 직접 참조해야 자연스러운 표현이 되기 때문(spec이 cross-file {colors.X} reference 미지원).

본 파일에서는 brand-neutral 컴포넌트(divider, page text, caption, chart color 등 — 공유 토큰만 사용)만 정의하고, brand-specific 컴포넌트(Button, Focus ring 등)는 brand 파일에서 자체 prose로 작성합니다.

Button

수치 · 규칙의 원본은 specs/components/button.md · specs/components/button.yaml 이다 — 2026-09-30 SEED Action Button 구조로 다시 썼다(v112). 이 절은 토큰과 닿는 자리만 모은다.

변형과 색

변형쓰는 곳바탕 → 누름 · 호버글자 · 아이콘
brandSolid서비스 핵심 액션 하나(Desk 거래 추가 · HR 휴가 신청)브랜드 채움 → 브랜드 누름(브랜드 파일)static-white
neutralSolid (기본)대부분의 CTA — 저장 · 확인 · 다음bg-neutral-inverted → bg-neutral-inverted-pressedfg-neutral-inverted
neutralWeakCTA 옆 보조(취소) · CTA 를 뺀 대부분의 액션bg-neutral-weak → bg-neutral-weak-pressedfg-neutral
criticalSolid되돌릴 수 없는 작업의 확정(주로 Alert Dialog)bg-critical-solid → bg-critical-solid-pressedstatic-white
brandOutlineSolid 보다 낮은 위계 — neutralOutline 과 짝투명 + stroke-neutral-weak 1px → bg-layer-default-pressed브랜드 글자(브랜드 파일)
neutralOutline가장 낮은 위계의 보조 액션투명 + stroke-neutral-weak 1px → bg-layer-default-pressedfg-neutral
ghost메뉴 · 툴바 · 목록의 가벼운 액션투명 → bg-layer-default-pressedfg-neutral · fg-neutral-subtle · 브랜드 글자 · fg-critical

브랜드마다 달라지는 건 브랜드 채움 · 누름과 브랜드 글자뿐이다 — 값과 대비는 DESIGN.hr.md · DESIGN.desk.md 의 Button 절. 한 화면의 Solid 버튼은 하나, 확인 창을 여는 삭제는 ghost + fg-critical 이다.

대비(라이트 · 다크, 글자 × 바탕):

조합라이트다크
neutralSolid16.41:113.42:1
neutralSolid 누름7.11:17.70:1
neutralWeak15.20:110.32:1
criticalSolid5.06:15.77:1
ghost fg-neutral-subtle × bg-layer-default5.50:16.09:1
ghost fg-critical × bg-layer-default5.06:16.08:1

모두 본문 4.5:1 을 넘는다. Outline 테두리(stroke-neutral-weak × bg-layer-default 1.23:1)는 글자가 버튼을 알려 주므로 1.4.11 대상이 아니다 — SEED 도 같다.

상태

상태표현
hovered누름 색(v106) — 마우스 기기에서만, 축소는 없다
pressed누름 색 + 세로 2px 거리 축소(v104 — Motion 의 눌림 피드백). 축소는 motion-duration-pressed-scale · motion-ease-pressed-scale, 색은 motion-duration-color-transition · motion-ease-easing
focusedstroke-focus-ring 2px · 띄움 2px(v106) — 키보드 포커스(focus-visible)에만
loading누름 색 위 로딩 원(Outline 은 투명 그대로), 라벨 자리 폭 유지 · 누르기를 막고 aria-busy="true"
disabledbg-disabled · fg-disabled(2.93:1 — 1.4.3 incidental 예외). 불투명도로 흐리게 하지 않는다(v106)

크기

크기높이좌우 여백글자모서리아이콘
xsmall32pxspacing-x3_5 (14px)t3 13pxradius-full (알약)14px
small36pxspacing-x3_5 (14px)t4 14pxradius-r2 (8px)14px
medium (기본)40pxspacing-x4 (16px)t4 14pxradius-r2 (8px)16px
large48pxspacing-x5 (20px)t6 18pxradius-r3 (12px)22px

글자 굵기는 모두 700. 아이콘만 있는 버튼은 정사각(높이 = 폭)이다. 크기는 이름이 아니라 높이로 고른다 — 모달 footer 는 small, 모바일 하단 CTA 는 large.

누르는 영역 · 배치

  • 누르는 영역은 보이는 크기와 따로 44 × 44 까지 넓힌다(v106) — 2.5.5 (AAA 44 × 44) 충족.
  • 2.5.8 (AA 24 × 24) 은 모든 크기가 충족한다.
  • 나란히 두는 버튼 사이는 8px, 셋까지. 화면 하단에 채운 두 버튼(닫기 · CTA)은 3:7 — 모달 footer 는 Dialog · Drawer 의 폭 나누기(지금은 균등)를 따른다.

Accessibility 체크리스트

  • keyboard: Enter / Space 로 누르고 Tab 으로 포커스가 들어온다
  • 아이콘만 있는 버튼은 aria-label 필수
  • 로딩은 aria-busy="true" — 포커스는 그대로 두고 누르기만 막는다
  • 비활성: aria-disabled="true" 는 포커스가 남고, disabled 속성은 포커스를 뺀다 — 흐름에 맞춰 고른다

Input · Textarea

수치 · 규칙의 원본은 specs/components/input.md · input.yaml(한 줄 — SEED Text Input)과 textarea.md · textarea.yaml(여러 줄)이다 — 2026-10-01 SEED Text Input · Textarea 구조로 다시 썼다. 라벨 · 설명 · 오류 · 글자 수는 Field(아래 Field 절)가 둘레에서 그린다. 이 절은 토큰과 닿는 자리만 모은다.

모양과 색

요소값
바탕투명 — 놓인 표면(bg-layer-default · bg-layer-floating)이 비친다
테두리안쪽 1px stroke-neutral-weak. 밑줄형은 아래만
포커스안쪽에 2px stroke-neutral-contrast 를 덧그린다 — 마우스 · 터치로 눌러도(입력 중). 내용은 밀리지 않는다. 읽기 전용이면 없다
오류안쪽 2px stroke-critical-solid — 포커스해도 그대로
비활성바탕 bg-disabled · 글자 · 아이콘 fg-disabled. 불투명도로 흐리게 하지 않는다(v106)
읽기 전용바탕 bg-disabled · 값은 fg-neutral 그대로(밑줄형은 바탕 없이 값 fg-neutral-muted)
값 · placeholderfg-neutral · fg-placeholder
앞 · 뒤 글자 · 아이콘 · 지우기fg-neutral-subtle · fg-neutral-muted · fg-neutral-subtle

덧그린 2px 의 색만 motion-duration-d2 (100ms) · motion-ease-easing 로 바뀐다 — 두께는 바로 바뀐다(SEED).

대비(라이트 · 다크, bg-layer-default 위): 값 16.41 · 13.42, 앞뒤 글자 5.50 · 6.09, placeholder 4.18 · 4.13(v119 — 4.5:1 밑, 사용자 결정 2026-10-16 글자 역할 D7), 포커스 테두리 16.41 · 13.42, 오류 테두리 5.06 · 6.08. 1px stroke-neutral-weak(1.23 · 1.56)는 칸을 알리는 유일한 표시가 아니다 — 라벨 · placeholder 가 함께 알린다(SEED 와 같다). lint 대비 쌍 input-light · input-dark(본문 × surface-input)는 읽기 전용 칸(값 × bg-disabled — 같은 색)을 잰다.

크기

크기높이좌우 여백글자모서리아이콘 · 지우기
large52pxspacing-x4 (16px)t5 16pxradius-r3 (12px)20 · 22
medium40pxspacing-x3_5 (14px)t4 14pxradius-r2 (8px)16 · 18
underline large40px(위아래 8)0t6 18px024 · 22
underline medium34px(위아래 6)0t5 16px020 · 18
  • 웹의 기본은 반응형 — 1280 미만 large, 이상 medium(SEED lg). 앱은 늘 large. medium 은 데스크톱 웹(마우스)에서만 — 폰에서 40 은 누르는 영역 44(AAA)에 못 미친다. 한 폼 안에서 크기를 섞지 않는다.
  • Textarea 는 상자형 하나 — 자동 높이 3줄(large 94 · medium 82, 위아래 14 · 12)에서 쓴 만큼 자라고, 끄면 2줄(72 · 62) 이상 고정 높이에서 칸 안 스크롤. 손잡이(resize)는 두지 않는다.

쓰는 규칙

  • 밑줄형은 화면에 입력이 하나뿐일 때(금액을 먼저 받는 화면 · 목록 위 검색 · 초대 코드 · 잠금 해제).
  • 단위는 칸 안 뒤 글자로 — 라벨에 "(원)" 을 붙이지 않는다. 금액은 숫자 키보드 · 천 단위 쉼표, type="number" 는 쓰지 않는다.
  • 고르는 값(날짜 · 시각 · 카테고리 · 자산)은 타이핑으로 받지 않는다 — Input Button 으로 시트 · 달력 · 목록을 연다.
  • 형식이 정해진 값(전화번호 · 주민등록번호)은 칸을 나누지 않는다 — 한 칸에서 형식을 맞춰 준다.
  • 지우기 버튼은 검색칸 · 선택 사항인 칸에, 값이 있을 때만(이름 "지우기").

Accessibility 체크리스트

  • 모든 칸에 라벨(Field) — placeholder 를 이름으로 쓰지 않는다
  • 오류면 aria-invalid, 설명 · 오류 · 글자 수 · 단위 글자는 aria-describedby
  • 포커스하면 테두리가 2px 로 짙어진다(키보드 · 마우스 모두)
  • 최대 글자 수는 자소 단위로 세고, 한글은 조합이 끝난 뒤 자른다

Select · Input Button

수치 · 규칙의 원본은 specs/components/select.md · select.yaml(짧은 선택지를 칸 아래 목록으로 — SEED Select)과 input-button.md · input-button.yaml(입력칸 모양의 버튼 — 시트 · 팝오버를 연다, SEED Input Button)이다 — 2026-10-01 사용자 결정. 라벨 · 설명 · 오류는 Field(아래 Field 절)가 둘레에서 그린다. 이 절은 토큰과 닿는 자리만 모은다.

나누기

이런 자리컴포넌트
짧은 선택지 5개 이상(한 줄 설명까지)에서 폼 값을 고른다Select — 칸 아래 목록. 폰에서도 시트로 바꾸지 않는다
달력 · 시각 · 아이콘 격자 · 검색해 고르는 긴 목록Input Button — 1280 미만 아래 시트 · 이상 칸 아래 팝오버
설명 · 그림 · 딸린 입력이 붙는 2 ~ 6개를 견줘 고른다Select Box
2 ~ 4개 짧은 선택지Chip — 글이 길면 Radio · Checkbox

트리거 · 칸

상자는 Input 의 상자형과 같다 — large 52 · medium 40 · 웹 기본 반응형(1280), 앱은 large. 모서리 radius-r3 · radius-r2, 투명 바탕 + 안쪽 1px stroke-neutral-weak, 오류 안쪽 2px stroke-critical-solid, 비활성 · 읽기 전용 bg-disabled(흐림 없음 — 읽기 전용의 값은 진한 글자). 버튼이라 Input 과 다른 자리:

요소값
누름 · 호버바탕 bg-layer-default-pressed + 값 · 아이콘만 2px 거리 축소(v104). 마우스는 호버에 같은 바탕
포커스키보드 포커스에만 바깥 링 2px · 띄움 2px stroke-focus-ring
셰브론(Select)20 · 16 fg-neutral-muted, 열리면 180°(열 때 motion-duration-d3 · 닫을 때 motion-duration-d2)
뒤 아이콘(Input Button)무엇이 열리는지 — 달력 · 시계 · 아래 화살표
지우기(Input Button)선택 사항인 칸에 값이 있을 때만, 22 · 18 fg-neutral-subtle — 값 뒤 · 뒤 붙이개 앞

목록(Select)

요소값
목록트리거 폭 · 아래 8(모자라면 위) · 모서리 radius-r5 · bg-layer-floating · shadow-s3 · 위아래 8 · 높이 min(480, 남은 화면 — 200 은 둔다)
선택지large 46 · medium 39(설명이 있으면 66 · 57) · 좌우 16, 글 t5 · t4 fg-neutral, 설명 t3 · t2 fg-neutral-subtle
고른 표시오른쪽 체크 14 · 12(선 2.5) fg-neutral — 바탕 · 굵기는 바꾸지 않는다
누름 · 호버 · 키보드 위치좌우 8 들인 알약(모서리 12) bg-layer-floating-pressed — 누르는 동안만 콘텐츠 2px 거리 축소
묶음제목 t4 500 · t3 400 fg-neutral-subtle, 묶음 사이 1px stroke-neutral-subtle(좌우 16 들임 — 8 + 1 + 8)
모션열 때 motion-duration-d3 · motion-ease-enter(0.95 → 1 · 투명 → 불투명), 닫을 때 motion-duration-d2 · motion-ease-exit

쓰는 규칙

  • 늘 Field 의 라벨과 함께. placeholder 는 "{값의 종류} 선택".
  • "없음" 이 답이면 "{칸 이름} 없음" 선택지를 맨 앞 따로 묶음에 — Select 에는 지우기 버튼이 없다. 꼭 골라야 하는 칸은 없음 없이 제출 때 오류, 늘 값이 있는 칸은 기본값을 골라 둔다.
  • 여럿 고르기는 열린 채 이어 고른다 — 칸에는 "식비, 교통", 넘치면 "식비 외 2개". 최대 개수는 Field 설명에, "전체 선택" 같은 선택지는 두지 않는다.
  • 선택지 글은 명사형으로 짧게 — 코드값(Y · N · ANNUAL)을 내지 않는다. 폼 값을 탭으로 고르지 않는다. 요일 7개도 여럿 고르는 Select.
  • Input Button 은 혼자 쓰지 않는다 — 늘 고르는 자리를 연다. 달력 · 시각은 "완료" 로 넣고(고르는 동안 칸의 값은 그대로), 목록은 누르면 바로 넣는다. 긴 목록은 검색 시트(Combobox 를 두지 않는다).

Accessibility 체크리스트

  • 모든 칸에 라벨(Field) — placeholder 를 이름으로 쓰지 않는다. 라벨을 누르면 포커스만(열지 않는다)
  • Select 트리거 role="combobox" · aria-expanded, 목록 role="listbox" · 선택지 role="option" aria-selected · 짚은 선택지 aria-activedescendant
  • Input Button 이름은 라벨 + 고른 값, aria-haspopup="dialog" · aria-expanded, 필수는 설명으로 "필수"
  • 키보드 포커스 링 — 트리거 · 칸
  • large 52 · 선택지 46 은 AAA 44 ✓, medium 은 1280 이상 데스크톱(마우스)에서만

Card

2026-10-08 — 원본은 specs/components/card.md · card.yaml(SEED 면 · Feedback). 옛 변형 넷(default · interactive · outline · flat) · 여백 네 단계 · 모서리 8 · hover 그림자 상승은 걷었다.

회색 바닥(bg-layer-basement) 위 흰 면(bg-layer-default) + 1px stroke-neutral-weak, 그림자 없음 — 폰 · 데스크톱 · 라이트 · 다크가 같은 규칙이다(사용자 결정 — 데이터 표시 비교 페이지 4A · 5A · 6B · 7A · 8B).

자리값
모서리16(radius-r4) — 카드 안 목록의 누름 바탕은 10(동심 모서리)
여백24(spacing-x6) — 폭과 상관없이. List 줄 · Bottom Sheet 와 같은 값이다(카드 24 = 줄 24 = 시트 24). 목록 카드는 좌우 0 — 줄이 제 좌우 24 를 갖고, 머리 위 · 좌우 24, 카드 아래 12(줄 12 와 합쳐 24)
카드 사이위아래로 쌓으면 8(spacing-x2 — SEED "8px Gap"), 데스크톱 격자 칸 사이는 layout-gutter 24
머리제목 16 / 22 · 700 · fg-neutral + 오른쪽 동작 하나("전체 보기" — 글 버튼: 14 · 700 · fg-neutral-muted · 보이는 36 · 꺾쇠 없음, 누르는 영역 44. Typography 의 "글자 역할" R16 — 2026-10-16 사용자 결정 D2 로 6B 의 14 · 500 · subtle + 꺾쇠를 바꿨다)
누름면 bg-layer-default-pressed + 2px 거리 축소 — 안에 대등한 동작이 있으면 색만(SEED Feedback). 그림자 상승 · 위로 뜨기 없음
지표 카드라벨 13 · 500 · fg-neutral-subtle · 숫자 24(데스크톱 격자에 셋 · 넷씩이면 20) · 700 · 고정폭 숫자 · 증감 줄(Colors 의 "증감 — 방향 색") — 폰은 한 줄에 하나, 숫자 굴림 애니메이션 없음
순자산 카드Desk 홈 · 자산 한 자리 — 브랜드 채움 135° + 흰 글자, 다크도 짙은 채움 · 증감도 흰 ▲ · ▼(Desk 파일의 Card 절)
카드 안 아코디언카드 상세의 혜택 · 유의사항(2026-10-10) — 좌우 0 · 머리 위 · 좌우 24 · 아래 4, 카드 아래 8(마지막 트리거 16 과 합쳐 24) · 머리 오른쪽에 모두 펼치기
  • 변형은 default · hero 둘이다. 그림자 카드 · 흰 위 흰 그림자 카드(raised) · 회색 채움(muted) · 브랜드 틴트(brand)는 두지 않는다 — 시트 · 대화상자 안의 요약은 List 키-값 줄 · Callout.
  • 카드 안에 카드를 두지 않는다. 카드의 데이터를 못 불러오면 그 카드 안에 Result Section medium + 다시 시도 — 화면 전체를 스켈레톤으로 되돌리지 않는다.
  • card-light · card-dark 짝(흰 면 · 다크 면 위 본문 글자)은 lint 가 대비를 재는 자리로 남긴다.

Page text

기록 — 기준은 Typography 의 "글자 역할"(2026-10-16)이다: 화면 제목 R1 · 화면 부제 R2 · 구역 제목 R4 · 긴 글 R11. 옛 내용(body-md 15 · 600 강조 · title-sm ~ title-md 헤딩 위계)은 DESIGN.history/v119-text-roles.md 에 있다.

Caption

기록 — 기준은 Typography 의 "글자 역할"(2026-10-16)이다: 줄 · 칸 안 설명 · 메타는 R9(fg-neutral-subtle 한 색 — 메타 줄은 Tag Group, specs/components/tag-group.md), 축 · 단위 · 범례 같은 덧붙인 정보는 R10. 옛 secondary / tertiary 위계(카테고리 muted · 시각 subtle)는 쓰지 않는다 — DESIGN.history/v119-text-roles.md.

Badge · Notification Badge · Tag Group

2026-10-03 SEED Badge · Notification Badge · Tag Group 구조로 다시 정했다(사용자 결정 — 비교 페이지 https://claude.ai/artifact/4ySVacsdnG4fgraR1HRK3G, 1A · 2A · 3A · 4A 와 "따라오는 것"). 수치 원본은 specs/components/badge.yaml · notification-badge.yaml · tag-group.yaml, 쓰는 규칙은 같은 이름의 .md 다. 옛 Badge 절(채운 의미 색 넷 · 18 · 22 · 28 · 알약 또는 모서리 4 · 개수는 aria-live)은 걷었다 — 옛 스펙은 specs/components/badge.history/v-pre-seed-display.*. 머리말의 badge-success · badge-error · badge-warning · badge-info 대비 쌍은 solid 배지의 흰 글자(라이트)를 잰다. 의미 색 outline 의 옅은 테두리 넷(stroke-critical-weak · stroke-positive-weak · stroke-warning-weak · stroke-informative-weak)을 이 묶음에서 들였다(v117).

나누기

보이려는 것쓰는 것
대상의 상태 · 분류(예정 · 연체 · 승인 · 신용)Badge — 누르지 않는다
설명 줄의 메타(카테고리 이름 · 자산 · 시각 · 거리 · 개수 · 금액)Tag Group — " · " 로 이은 글줄
안 읽은 알림이 있음 · 몇 개Notification Badge — 점 · 숫자
고르기 · 거르기 · 넣은 값 빼기Chip — 누르는 알약(Chip 절)

모양

BadgeNotification BadgeTag Group
크기medium 20(좌우 6 · 위아래 2 · 글 11/15) · large 24(8 · 4 · 12/16), 앞 아이콘 12 · 14점 6 · 숫자 18(좌우 4 · 11/15 · 700 — 글자 크기 설정을 따르지 않는다)12/16(기본) · 13/18 · 14/19, 아이콘 12 · 13 · 14
모양둥근 사각 — 모서리 radius-r1 4 · radius-r1_5 6. 알약은 Chip 에만원 · 알약글 — 항목 사이 " · " 글자(앞 항목에 붙는다)
색weak bg-*-weak + fg-*-contrast · 500 / solid bg-*-solid + static-white · 700 / outline 투명 + 안쪽 1px stroke-*-weak + fg-* · 700. 중립은 bg-neutral-weak + fg-neutral-muted · bg-neutral-inverted + fg-neutral-inverted · stroke-neutral-weak, warning solid 는 주황 + 흰 글자점은 브랜드 글자색(다크에서 밝은 짝), 숫자는 브랜드 채움 + 흰 글자 — 브랜드 파일기본 fg-neutral-subtle(흰 바탕 5.50) · 앞세울 항목 fg-neutral 700 · 구분 fg-disabled
자리줄 · 상세 머리 — 한 대상에 둘까지, 사이 4아이콘 상자 기준 — 점 오른쪽 위 안쪽 1(24 아이콘 x 17 ~ 23 · y 1 ~ 7), 숫자 왼쪽 아래 꼭짓점 (아이콘 폭 − 8, 14). 글이면 끝 + 2 · 줄 상자 위List 의 설명 줄 · 카드 · 상세 머리의 메타

쓰는 규칙

  • 배지는 누르지 않는다 — 누르는 라벨은 Chip(알약). 배지의 뜻을 더 알려야 하면 옆에 ⓘ Help Bubble.
  • 반복되는 목록은 weak — 한 목록 안은 한 변형, 뜻은 톤으로. brand 는 요금제 · 본인 표시처럼 브랜드와 닿는 자리에만.
  • 흰 표면 위에 — 중립 weak 의 바탕은 회색 바탕(bg-layer-basement)과 같은 색이라 거기서 사라진다.
  • 합계에 안 드는 줄(예정 · 환불)은 흐리지 않는다 — 제목 · 금액만 fg-neutral-subtle, 환불 금액은 취소선, 배지는 보통 대비(List 절).
  • 알림 점 · 숫자는 확인할 새 것에만 — 보면 사라진다. 0 은 안 보이고 100 이상은 "99+". 한 화면에 아껴서(여러 탭에 동시에 달지 않는다).
  • 메타 줄 구분은 " · " 글자 — 2px 점 그림 · "•" 를 쓰지 않는다. 항목은 6 ~ 10자, 한 묶음은 한 크기.
  • 글 — 배지 · 메타에 영어 · 코드값을 내지 않는다("NEW" → "새로", ROLE_ADMIN → "관리자", "Day 2 of 3" → "2/3일째", "9:00 AM" → "오전 9:00"). 요금제 이름 Pro · Free 는 그대로.

접근성

  • Badge: 역할 없는 글 — 줄 이름에 이어 읽힌다. 뜻은 글이 말하고 색은 거든다. 모든 짝이 4.5:1 이상이다.
  • Notification Badge: 점 · 숫자는 숨기고 붙은 버튼 · 탭 이름에 넣는다("알림, 새 알림 3개"). 수가 바뀌어도 소리로 알리지 않는다(라이브 영역 없음).
  • Tag Group: 구분 " · " 는 숨기고 그 자리에 보이지 않는 ", " — 항목마다 끊어 읽는다. 뜻이 있는 아이콘 항목은 읽을 글("분할 2건")을 준다.

Alert text

기록 — 기준은 Callout(specs/components/callout.md — 2026-10-02, 본문 t4 · 제목 700 · 톤 contrast 색)과 Field 오류(Typography 의 "글자 역할" R19 — t4 · fg-critical + 아이콘)다. 옛 alert-text 짝 · body-md 15 · 600 제목은 DESIGN.history/v119-text-roles.md 에 있다.

Focus ring

모든 인터랙티브 컴포넌트(button / input / card-interactive / link / tab 등)의 focus 표현 통일 — 키보드 사용자의 시각적 navigation cue.

Mode pair (sparse — brand 토큰이 contrast 검증 담당)

  • focus-ring-on-light (focus-ring-on-light): 라이트 표면 위 focus
  • focus-ring-on-dark (focus-ring-on-dark): 다크 표면 위 focus

(색은 역할 색 stroke-focus-ring 하나다(v102) — 라이트 · 다크 값은 brand 파일의 v102 표, 그룹 화면은 이 파일의 짙은 회색(2026-10-23 "그룹 색 · 로고 칠"). 옛 border-focus · border-focus-light 는 같은 값의 별칭이다.)

Spec

  • 두께: 2px outline (1px은 시인성 부족)
  • offset: 컴포넌트 외곽 2px (즉 컴포넌트 + 2px gap + 2px ring → 총 4px 외곽 영역 — v106, 스펙 다수와 맞춤)
  • 입력칸 · 선택 상자: 입력 중에는 링 대신 같은 색의 테두리 2px(v106 — State 절)
  • shape: 컴포넌트 outline 100% 둘러쌈 — border-radius 동일 적용
  • trigger: focus-visible pseudo만 (마우스 클릭 시 미표시, Tab/keyboard로 진입 시만)

WCAG 검증

  • 2.4.11 Focus Appearance (AA — 2.2): focus indicator는 (a) 인접 표면 대비 3:1 이상, (b) 컴포넌트 외곽선 둘레의 최소 2 CSS pixel 두께 + 인접한 비-focus 상태 대비 3:1 충족 — 본 시스템 모두 충족
  • 2.4.12 Focus Not Obscured (Minimum) (AA — 2.2): focus 받은 요소가 author-created 컨텐츠에 의해 완전히 가려지면 안 됨 — sticky header / popup overlay 디자인 시 z-index + scroll-margin 고려
  • 2.4.13 Focus Appearance Enhanced (AAA — 2.2): 컴포넌트 둘레 둘레 100% × 두께 4 CSS pixel 또는 기준 2배 이상 대비 권장 — 향후 enhanced focus 옵션 (focus-ring-enhanced 토큰) 추가 후보

사용 예시 (CSS 의사코드)

.button:focus-visible {
  outline: 2px solid var(--color-stroke-focus-ring); /* 다크 값은 다크 블록이 바꾼다 */
  outline-offset: 2px;
}

Layout

  • focus ring은 outline 사용 (box-shadow도 가능하지만 outline이 layout shift 없음 — focus 시 element 크기 안 변함)
  • offset 2px → outline-offset: 2px (v106)

Motion

  • focus ring 등장: motion-duration-color-transition × motion-ease-easing (opacity 0 → 1) — v106, v104 이름으로
  • prefers-reduced-motion: reduce 시 즉시 표시 (focus 인지 지연은 a11y 저해)

Accessibility 체크리스트

  • 2.4.11: 모든 컴포넌트의 focus state는 focus-ring-on-{light,dark} 토큰 사용
  • focus-visible만 사용 — 마우스 사용자 방해 없음 (:focus로 일관 적용 시 클릭 후에도 ring 표시되어 산만)
  • 2.4.12: focus 가려짐 방지 — sticky header 아래 focus 받으면 자동 scroll 보강 (scroll-margin-top: <header height>)
  • 다크 모드 자동 전환: [data-theme="dark"] 또는 prefers-color-scheme: dark 블록이 --color-stroke-focus-ring 을 다크 값으로 바꾼다

Divider

2026-10-03 SEED Divider 로 다시 정했다(옛 Separator 를 대신 — 사용자 결정, 비교 페이지 https://claude.ai/artifact/4ySVacsdnG4fgraR1HRK3G 의 "따라오는 것"). 수치 원본은 specs/components/divider.yaml, 쓰는 규칙은 divider.md 다. 옛 절(border-default 1px · dashed 예약 · margin-only)은 걷었다 — 옛 스펙은 specs/components/separator.history/v-pre-seed-display.*. 머리말의 divider-light · divider-dark 는 옛 v40 짝(값은 옛 border-default)이고, 글자가 없어 대비 검사 대상이 아니다.

세기쓰는 것자리
약함들인 선 — 양끝 16같은 묶음 안
중간끝까지 선묶음 사이 · 액션 영역 위 · 스크롤되는 본문 위 머리
강함8 간격 — 회색 바탕(bg-layer-basement) 위 흰 층(bg-layer-default) 사이. 선이 아니다크게 다른 내용 사이
  • 선은 하나 — 1px stroke-neutral-subtle(흰 바탕 1.15 · 다크 1.30, SEED 기본 neutral-muted 와 같은 진하기 — 새 토큰 없이). 굵은 선 · 짙은 선 · 점선 · "8px 구분선" 을 두지 않는다.
  • 가로(부모 폭) · 세로(부모 높이 — 통계 세 칸 사이). 바깥 여백이 없다 — 간격은 쓰는 자리가 정한다.
  • 반복되는 목록 줄 사이는 List 의 줄 사이 선(기본 없음 · 같은 색 · 들임 24). 화면 · 묶음의 마지막 아래에는 두지 않는다.
  • 기본은 장식(보조 기술에 숨김) — 이름 있는 구획을 나눌 때만 role="separator"(SEED 는 <hr> 가 기본).
  • 웹 · 앱의 border-subtle 과 border-default 가 같은 값이라 "옅은 구분선" 이 효과가 없다 — 구분선은 이 한 색으로 정리한다.

Outline (border 시각 요소 · 기록 — 기준은 Dialog · Popover 스펙과 v104 의 선)

border-strong 토큰을 1px element의 배경색으로 사용 — 외곽선이 카드/section의 외곽 식별 강도를 높일 때.

Mode pair

  • outline-strong-light (outline-strong-light): border-strong (#7D8593) 사용
  • outline-strong-dark (outline-strong-dark): border-strong-dark (#838997) 사용

Spec

  • 두께: 1px (border CSS 또는 1px element)
  • 색상: border-strong (default border보다 강한 식별)

사용 시나리오

  • modal/dialog 외곽선 (shadow-xl + outline-strong-light 1px) — focus 가려짐 방지(2.4.12) 시 시각 분리감 보강
  • highlighted card (선택된 list item, drag-over state)
  • inline editor의 in-progress 표시

Contrast (UI 1.4.11)

  • border-strong (#7D8593) vs surface-default (#FFFFFF) = 3.34:1 ✅ UI
  • border-strong vs bg-page (#F5F6FA) = 3.13:1 ✅ UI (3:1 통과)
  • border-strong vs surface-input (#F5F6FA) = 3.87:1 ✅ UI
  • border-strong-dark (#838997) vs bg-page-dark (#1A1F2E) = 4.68:1 ✅ UI
  • border-strong-dark vs surface-default-dark (#242938) = 4.13:1 ✅ UI
  • border-strong-dark vs surface-input-dark (#353B4D) = 4.05:1 ✅ UI

모든 표면에서 UI 1.4.11 (3:1) 통과 — 단순 외곽선만으로 컴포넌트 식별 가능.

Accessibility

  • 1.4.11: 위 contrast 충족 — outline-strong은 외곽선 단독 식별 가능 (border-default 1.16:1과 다름)
  • 다크 모드에서 modal에 outline-strong-dark + shadow-xl-dark 동시 사용 권장 (다크 표면 위 elevation 보강)

Disabled label (기록 — 기준은 v106 상태 — 막힌 글자 fg-disabled · 바탕 bg-disabled, 불투명도를 쓰지 않는다)

비활성 상태 컴포넌트(disabled button/input/menu item)의 텍스트 라벨. WCAG 1.4.3 incidental 예외 명시 — 사용 불가 컴포넌트 텍스트는 본문 4.5:1 비대상.

Mode pair (sparse — textColor만 정의, backgroundColor 없음)

  • disabled-label-light (disabled-label-light): text-disabled (#8A91A0)
  • disabled-label-dark (disabled-label-dark): text-disabled-dark (#838997)

contrast 참고 (incidental 예외라 통과 비대상):

  • text-disabled (#8A91A0) on surface-default (#FFFFFF) = 약 3.16:1 (본문 4.5:1 미달, AA UI 3:1 통과 — 시인성은 있되 본문 의도 아님)
  • text-disabled-dark (#838997) on surface-default-dark (#242938) = 약 4.13:1 (동일 패턴)

의도

WCAG 1.4.3 (Contrast Minimum)의 명시적 예외:

Text or images of text that are part of an inactive user interface component, that are pure decoration, that are not visible to anyone, or that are part of a picture that contains significant other visual content, have no contrast requirement.

→ disabled 컴포넌트의 라벨은 인터랙션 불가 상태를 시각적으로 알리는 역할이라 일부러 약한 contrast 사용. 4.5:1 통과해버리면 active 상태와 구분이 어려워 오히려 UX 저해.

Spec

  • text color: text-disabled / text-disabled-dark
  • 추가 시각(v106): 불투명도를 쓰지 않는다 — 배경이 있으면 bg-disabled, 테두리는 stroke-neutral-weak, cursor:not-allowed (State 절)

Layout

  • disabled 컴포넌트 옆의 이유 글(예: "비활성화됨" 부가 설명)은 Field 설명과 같은 t4 · 400 · fg-neutral-subtle(Typography 의 "글자 역할" R9)로 4.5:1 을 지킨다 — 이 글은 incidental 예외 비대상

Accessibility

  • 1.4.3 incidental 예외 — text 자체 contrast는 비대상
  • 그러나 시각적 비활성 표현 보강 필수: 전용 색(bg-disabled · fg-disabled · stroke-neutral-weak) + cursor:not-allowed (v106 — 불투명도 0.5 는 걷음)
  • aria: disabled HTML 속성 (form 제어) 또는 aria-disabled="true" (focus 가능, 메뉴 아이템 등)
  • screen reader가 "비활성화됨"이라고 읽음 — 시각적 강조 없이도 전달
  • disabled 컴포넌트 옆에 reason text 권장 (예: "권한 없음", "기간 만료") — 글자 역할 R9 값으로

Chart color (palette)

data visualization(bar/line/pie/donut/heatmap)·카테고리 색상·tag 분류용 10색 palette. fill / stroke 용도 sparse 매핑(backgroundColor만, textColor 페어 비대상).

Mode pair (10색 × 2 = 20 토큰)

Light surface (surface-default 위) — 팔레트 700 단계(v110, L* 45 ~ 50):

TokenhexHue
chart-color-red#D72323red
chart-color-orange#BE490Dorange
chart-color-yellow#8C7400yellow
chart-color-green#167F3Fgreen
chart-color-blue#1D6EC9blue
chart-color-indigo#5E60C8indigo
chart-color-violet#8B4DBAviolet
chart-color-pink#B83B7Apink
chart-color-brown#9A6536brown
chart-color-gray#62697Agray

Dark surface (surface-default-dark 위) — chart-*-dark = 팔레트 800-dark(v110, L* 69):

Tokenhex
chart-color-red-on-dark#FF8477
chart-color-orange-on-dark#FF8758
chart-color-yellow-on-dark#C5A721
chart-color-green-on-dark#25C062
chart-color-blue-on-dark#69ABFF
chart-color-indigo-on-dark#99A1FE
chart-color-violet-on-dark#C793F3
chart-color-pink-on-dark#F485B6
chart-color-brown-on-dark#CF9F77
chart-color-gray-on-dark#B7BDCC

Hue 정렬 의도

red → orange → yellow → green → blue → indigo → violet → pink → brown → gray 는 표의 차례(무지개 + 보조색)다. 차트에서 색을 받는 차례는 v110 의 배정 순서(blue → green → orange → violet → pink → indigo → red → yellow → brown)이고 회색은 "기타" 전용이다 — 저장된 색이 있으면 아직 쓰지 않은 색부터(2026-10-08, specs/components/chart.md).

L 통일의 의도

모든 chart 색상은 동일한 명도 → 휘도 차이로 인한 시각 우선순위 부여 없이 hue 차이만으로 카테고리 구분. 이는 색맹 사용자(특히 적-녹 색맹)에게 부분적 도움 — 명도 차이가 없으면 고대비 hue 색상도 동일 톤으로 보일 수 있어 반드시 패턴/라벨 보강 필수.

Variant

사용Token 그룹비고
라이트 표면 fillchart-color-{hue}bar 채움, pie slice
라이트 표면 strokechart-color-{hue}line 그래프 stroke
다크 표면 fill/strokechart-color-{hue}-on-dark다크 모드에서 chart-{hue}-dark 사용
카테고리 tagchart-color-{hue}category badge, label dot
작은 면 옅은 바탕(v111)chart-{hue}-weak + 글자 chart-{hue}-contrast · 아이콘 chart-{hue}카테고리 타일 · 캘린더 칩 · 주식 나라 표시
넓은 면 옅은 바탕(v111)chart-{hue}-subtle + 글자 chart-{hue}-contrast메모 카드 · 배너

Layout

  • pie/donut: 10개를 넘으면 상위 9 + 회색 "기타"(v110)
  • bar/column: 카테고리 ≤7 권장
  • line graph: ≤5 lines (더 많으면 지표 타일로 계열을 골라 보게 — 나머지를 회색으로 칠하지 않는다)
  • 범례: 선 · 막대는 차트 위 지표 타일, 도넛은 카테고리 목록(2026-10-08 — specs/components/chart.md)

Motion

  • chart entrance: motion-duration-slow (300ms) × motion-ease-out — 막대 grow / 선 draw 자연스럽게
  • hover highlight: motion-duration-fast (150ms) opacity 변화
  • prefers-reduced-motion: reduce 시 즉시 표시 (애니메이션 없이)

Accessibility

  • 1.4.1 Use of Color (강조): chart에서 색상 단독 의존 절대 금지 — 패턴(diagonal/dot 등) 또는 라벨 직접 표시 보강 필수. 특히 적-녹(red/green) 동시 사용 시 색맹 대응 필수
  • 1.4.11 Non-text Contrast: chart element vs surface 대비 3:1 이상 — chart-color-yellow (#8C7400) vs surface-default = 4.55:1 ✅, 가장 약한 hue도 UI 3:1 통과
  • legend / data label: 각 색상 옆에 텍스트 라벨 또는 패턴 표시. 시각만으로 식별하는 chart 금지
  • screen reader: chart는 <table> fallback 또는 <svg role="img" aria-label="..."> + 데이터 요약 텍스트 동반
  • focus: 차트 상자 하나가 초점을 받고 ← · → 로 날짜를 옮기며 툴팁을 띄운다(2026-10-08 — specs/components/chart.md). 데이터 점마다 tabindex 를 두지 않는다

사용 예시 (CSS 의사코드)

.chart-bar-1 { background-color: var(--color-chart-color-red); }
.chart-bar-1[data-pattern="diagonal"] {
  background: repeating-linear-gradient(45deg, var(--color-chart-color-red), var(--color-chart-color-red) 4px, transparent 4px, transparent 8px);
}
@media (prefers-color-scheme: dark) {
  .chart-bar-1 { background-color: var(--color-chart-color-red-on-dark); }
}

시트 · 대화상자 · 확인창 · 팝오버

수치 · 규칙의 원본은 specs/components/bottom-sheet.md · dialog.md · alert-dialog.md · popover.md 와 각 .yaml 이다 — 2026-10-02 SEED Bottom Sheet · Dialog · Responsive Dialog · Alert Dialog · Popover 구조로 새로 정했다(옛 Modal · Drawer · Alert Dialog · Popover 절을 대신한다). 이 절은 토큰과 닿는 자리만 모은다.

나누기 — 떠 있는 표면 일곱, 상황 → 고를 것

떠 있는 표면 일곱(Bottom Sheet · Dialog · Alert Dialog · Popover · Menu · Menu Sheet · Side Panel)을 고르는 표는 여기 한 벌이다 — 각 스펙은 고르는 순간 헷갈리는 짝 비교 표(Dialog ↔ Alert Dialog · Alert Dialog ↔ Menu Sheet)만 두고 이 표로 링크한다(2026-10-22 사용자 결정 3C — 떠 있는 표면 정리 페이지 https://claude.ai/artifact/YRPbWzhgD4EDdKsVioU8Zj).

이런 일1280 미만1280 이상닫는 법 · 주의
지금 화면을 떠나지 않고 쓰는 입력 폼(거래 추가 · 수정)Bottom SheetDialog — 한 부품(Responsive Dialog)이 폭으로 바꾼다바깥 · 끌기로 닫히지 않는다. 바뀐 값이 있으면 묻는다
한 건의 상세 조회(거래 상세)Bottom SheetDialog — 목록을 보면서 다뤄야 하면 Side Panel(오른쪽)머리 닫기 · 바깥 · Esc 로 닫힌다
칸에 넣을 값 고르기(날짜 · 시각 · 아이콘 · 긴 목록)Bottom Sheet(Input Button)Popover고르면 바로 들어가거나 "완료"
트리거 옆 짧은 안내(규정 · 계산식)Bottom SheetPopover제목 + 닫기. 몰라도 일은 할 수 있는 설명은 Help Bubble
Desk 데스크톱 벨의 알림 목록(768 이상)Bottom Sheet(768 ~ 1279)Popover — 벨 아래(2026-10-16 사용자 결정 Q-017-3b B)길이가 데이터에 따라 는다 — 끝 흐림
줄 · 화면의 동작 목록(수정 · 복사 · 삭제)Menu SheetMenu고르면 닫히고 실행
되돌릴 수 없는 일의 확인(삭제 · 나가기)Alert DialogAlert Dialog고르기 전에는 못 지나간다
꼭 알아야 할 결과 알림(지울 수 없어요)Alert Dialog(single)Alert Dialog(single)버튼 하나("확인")
주 메뉴(HR 폰)Side Panel(왼쪽)— (사이드바)이동하면 닫힌다
처음부터 화면 높이를 넘는 내용 · 단계가 많은 일(자산 상세 — 2026-10-23 계좌 3-B)페이지페이지주소 · 뒤로 가기가 따라온다. 작은 화면 · 큰 글자로 넘친 시트는 본문만 스크롤(Bottom Sheet)

오른쪽 Side Panel 은 지금 쓰는 곳이 없다(1280 미만은 Bottom Sheet). 값 · 동작은 각 스펙이 정한다 — 이 표는 고르는 법만 적는다.

모양

표면값
공통표면 bg-layer-floating, 딤 overlay-dim-light · overlay-dim-dark(Popover 는 딤 없음), 시트 · 대화상자 · 확인창은 그림자 없음
Bottom Sheet최대 480 · 위 모서리 radius-r6 · 머리 위 24 · 제목 t8 22 · 700 · 설명 t5 fg-neutral-muted · 좌우 spacing-global-gutter · 닫기 28 원(bg-neutral-weak, 누르는 영역 44) · 손잡이는 스냅 높이를 둘 때만 · 넘칠 수 있는 본문은 Scroll Fog 위 20 · 아래 80 · 바닥 버튼 large 48 + 안전 영역 · motion-duration-d6 motion-ease-enter-expressive 로 올라오고 d4 exit 로 내려간다
Dialogmedium 480 · large 800 · 최대 높이 80% · radius-r5 · 머리 24 · 제목 t8 · 본문만 스크롤(넘칠 수 있는 본문은 Scroll Fog — 늘 켜진 위 20 · 아래 80, 위로 스크롤하면 머리 아래 1px stroke-neutral-subtle) · 바닥 버튼 small 36 오른쪽 · d4 enter-expressive 로 1.3 배에서 줄며 나타남
Alert Dialog최대 272 · radius-r5 · 안쪽 20 · 제목 t7 20 · 700 · 설명 t5 fg-neutral(짙은 글자) · 버튼 둘 나란히(길면 세로 · 확정 위) — 1280 미만 medium 40 · 이상 small 36
Popover폭 320 ~ 480 · 최대 높이 600 · radius-r5 · shadow-s3 · 트리거와 8 · 머리 제목 t7 + 닫기 · d3 enter 로 0.95 배에서 커진다
쌓임specs/z-index.md — 시트 · 대화상자 L2(z-modal 100 · z-modal-content 101) · Popover L3(z-floating 200) · Alert Dialog L5(z-alert 300 · z-alert-content 301)

쓰는 규칙

  • 입력 폼은 바깥 누르기 · 끌어내리기로 닫지 않는다 — 닫기 버튼 · 취소 · Esc · 뒤로 가기로 닫고, 바뀐 값이 있으면 "작성한 내용이 사라져요" 를 묻는다(Field).
  • 닫기 버튼과 바닥 취소를 함께 두지 않는다 — 대화상자의 입력 폼은 바닥 [취소] [저장], 시트의 입력 폼은 위 닫기 + 바닥 [저장], 조회 · 안내 · 고르기는 위 닫기.
  • 확인창은 닫기 버튼이 없고 바깥 누르기를 무시한다. Esc 는 취소. 확인창 안에 입력칸을 두지 않는다.
  • 버튼 글은 동작 이름("삭제" · "저장" · "그룹 삭제") — "확인" 으로 뭉뚱그리지 않는다. 예외는 고를 것이 없는 결과 알림(Alert Dialog single)의 "확인" 하나다(2026-10-22 사용자 결정 5B).
  • 확인창은 대상을 이름으로 짚는다 — 제목이든 설명이든, 같은 동작은 어디서 불러도 같은 글(6B).

Accessibility 체크리스트

  • 모달(시트 · 대화상자 · 확인창) — role="dialog" · 확인창 role="alertdialog", aria-modal="true", 제목 aria-labelledby · 설명 aria-describedby, 열면 표면으로 초점 · 닫으면 연 자리로, 열린 동안 초점을 가두고 뒤 화면을 숨기고 스크롤을 잠근다
  • Popover — role="dialog"(aria-modal 없음), 초점은 안으로 · 가두지 않음 · Tab 으로 나가면 닫힘, 트리거 aria-haspopup="dialog" · aria-expanded
  • 닫기 버튼 이름 "닫기", 시트 닫기 누르는 영역 44
  • 대화상자 높이 80% 상한 — 머리 · 바닥이 화면 밖으로 나가지 않는다

알림 메시지 — Snackbar · Callout · Page Banner · Result Section

2026-10-02 SEED Snackbar · Callout · Page Banner · Result Section 구조로 다시 정했다(사용자 결정 — 비교 페이지 https://claude.ai/artifact/8t85WkZ3HLhMu8KibW3Vk1). 수치 원본은 specs/components/snackbar.yaml · callout.yaml · page-banner.yaml · result-section.yaml, 쓰는 규칙은 각 스펙 md 다. 옛 Toast 절(흰 카드 · 위 오른쪽 · 3장 쌓기 · 오류 8초)과 Sonner(v72) · Banner(v73) 절은 걷었다. 반전 짝 역할 셋(v115 — fg-brand-inverted · fg-positive-inverted · fg-critical-inverted)을 이 묶음에서 들였다.

나누기

무엇으로 알리나 — 상황 → 고를 것 표와 다섯 부품(Snackbar · Callout · Page Banner · Result Section · Alert Dialog) 견주기 표는 specs/components/snackbar.md 의 "무엇으로 알리나" 한 벌이다(2026-10-22 사용자 결정 3B — 알리고 기다리는 것 정리 페이지 https://claude.ai/artifact/NuEPiLRH2fJidXdKzcDsCX). 나누는 법은 일로 나눈다 — 방금 한 일의 결과 · 가벼운 실패는 Snackbar, 그 자리의 안내 · 오류는 Callout, 페이지 전체의 상태는 Page Banner, 비어 있음 · 실패 · 완료는 Result Section, 되돌릴 수 없는 결정 · 꼭 알아야 할 일은 Alert Dialog.

오류는 자리에서 알린다 — 모든 실패를 한곳에서 토스트로 띄우지 않는다(서버가 보낸 글 · 영어 · 코드를 그대로 보이지 않는다). 시트 · 대화상자에서 한 일은 창이 열린 채 봐야 하면 그 안 Callout, 창을 닫으며 끝나면 닫힌 뒤 토스트, 칸 하나가 틀리면 칸 아래다(2B).

모양

SnackbarCalloutPage BannerResult Section
자리화면 아래 가운데 · 탭 바 · 플로팅 버튼 위 8 · 최대 464본문 안 · 콘텐츠 폭페이지 맨 위 · 화면 폭놓인 자리 가운데
면bg-neutral-inverted(다크는 밝은 띠) · 모서리 8 · 그림자 없음bg-*-weak · 모서리 10bg-*-weak · bg-*-solid · 모서리 0없음
크기 · 여백최소 44 · 10 + 6(글은 16)최소 50 · 14최소 40 · 10 / 24좌우 48 · 위아래 16
글14 / 1914 / 19 · 제목 700 · 한 문단14 / 19 · 제목 700 · 본문 500제목 22 / 30 · 16 / 22 · 설명 muted
아이콘24 — 성공 · 실패만(fg-*-inverted)16 · 톤 색16 · 톤 색40
버튼액션 하나 · fg-brand-inverted 14 · 700링크 · 전체 누르기 · 닫기글 버튼 하나 13 · 700 · 닫기neutralWeak 40 + 글 버튼
시간 · 쌓임4초 · 액션 6초 · 머무는 동안 멈춤 · 한 번에 하나(새 띠는 바로 바꾸고, 액션이 달린 띠만 끝날 때까지 지킨다 — 1B) · z L6(400)늘 보임늘 보임 · 한 화면 하나늘 보임

톤은 다섯(neutral · informative · positive · warning · critical) — 옅은 바탕은 bg-*-weak + fg-*-contrast, 짙은 바탕은 bg-*-solid + 흰 글(static-white). 아이콘은 lucide 선 아이콘(v106).

쓰는 규칙

  • 글 — 해요체 문장에 마침표(스낵바도 — Writing v106). 무엇이 됐는지 먼저("거래를 저장했어요."), 오류는 할 수 있는 일까지. "실패" 로 끝나는 말 · 서버가 보낸 글 · 영어 · 코드를 쓰지 않는다. 액션은 동작 이름("되돌리기").
  • 닫기 — Callout · Page Banner 는 한 번 보면 되는 안내에만 닫기를 두고, 닫은 것을 기억한다. 경고 · 오류는 닫지 못한다.
  • 실패는 비어 있음과 다르게 — 불러오기 실패를 "내역이 없어요" 로 보이지 않는다. Result Section 의 실패 + "다시 시도".

접근성

  • Snackbar: 자리 aria-live="polite" · 띠 role="status" + aria-atomic, 초점을 옮기지 않는다. 보조 기술용 닫기는 키보드 초점이 오면 보인다.
  • 나중에 나타나는 경고 · 위험(Callout · Page Banner)은 role="alert". Result Section 은 결과로 바뀌면 role="status", 제목은 제목 태그.

메뉴 · 메뉴 시트 · 도움말 말풍선 · 툴팁

2026-10-02 SEED Menu · Menu Sheet · Help Bubble · Help Bubble Tooltip 구조로 다시 정했다(사용자 결정 — 비교 페이지 https://claude.ai/artifact/QoxJ7ZmQCedRWfPQrDvFgA, 여덟 다 SEED 쪽). 수치 원본은 specs/components/menu.yaml · menu-sheet.yaml · help-bubble.yaml(툴팁도 이 파일), 쓰는 규칙은 각 스펙 md 다. 옛 Tooltip 절(반전 · 모서리 4 · 240 · hover 500ms)과 Dropdown 절(테두리 1px · 모서리 8 · 줄 36 · menu · select · multi-select · combobox 변형)은 걷었다 — 값 고르기는 Select · Input Button 절, 메뉴는 여기. Menubar · Hover Card · Context Menu 는 세 제품 모두 쓰는 곳이 없어 걷었다.

나누기

이런 일1280 미만1280 이상
줄 · 화면의 동작(수정 · 복사 · 삭제 · 내보내기)Menu SheetMenu
값 고르기(테마 · 정렬 · 보기)테마는 List 라디오 줄, 정렬 · 보기는 Segmented Control · Select — 메뉴가 아니다(고르는 표는 specs/components/select.md 의 "고르는 컴포넌트 고르기" 한 곳 — 2026-10-22 1B)같다
아이콘 버튼 · 줄인 글의 짧은 설명— (툴팁은 터치에서 안 열린다 — 이름은 aria-label)Tooltip
몰라도 일은 할 수 있는 설명(규정 · 계산 방법)Help Bubble(ⓘ 를 눌러서)Help Bubble
버튼 · 고르는 칸이 있는 내용Bottom SheetPopover — 저장해야 남는 입력은 칸 하나라도 Dialog(위 "시트 · 대화상자 · 확인창 · 팝오버" 의 나누기)

모양

MenuMenu SheetHelp Bubble · Tooltip
표면bg-layer-floating · 모서리 20 · shadow-s3 · 폭 200 · 위아래 8bg-layer-floating · 위 모서리 20 · 최대 480 · 손잡이 늘 · 딤bg-neutral-inverted · 모서리 12 · 최대 280 · 화살표 12×8 · 그림자 없음
줄 · 글39(설명 있으면 57) · t4 14 · 아이콘 18 · 좌우 1652 · t5 16 · 아이콘 22 · 묶음 bg-neutral-weak 모서리 16t3 13(제목 700) · 위아래 10 좌우 12
누름 · 호버좌우 8 들인 알약 bg-layer-floating-pressed · 내용만 축소줄 bg-neutral-weak-pressed · 내용만 축소 — 설명은 fg-neutral-muted · 위험 글자는 fg-critical-contrast 로(누름 바탕 위 4.5:1)닫기 버튼만 축소
키보드알약 자리 2px 링(호버와 따로) · ↑↓ 순환 · 한 글자 찾기줄 안쪽 링 · Tab닫기 버튼 안쪽 링(말풍선 글자색)
묶음 · 위험묶음 사이에만 선 · 위험은 맨 아래 묶음 fg-critical묶음 사이는 간격 · 위험은 맨 아래 묶음—
z-indexL3 z-floating 200L2 z-modal 100 / z-modal-content 101L4 z-tooltip 210

쓰는 규칙

  • 메뉴는 실행만 — 누르면 바로 실행하고 닫힌다. 고른 표시(체크 · 라디오) · 단축키 · 하위 메뉴가 없다.
  • 목록 줄에는 ⋮ 를 두지 않는다 — 좁은 목록 줄(List 줄 — 한두 줄 글 + 타일 · 값)은 누르면 한 단계 들어가고(상세 · 수정), 동작은 들어간 화면에 둔다. 하나(삭제)면 바닥 왼쪽 [삭제] ghost + critical(Button 모달 footer 꼴 — 1280 미만 시트도 같다), 여럿이면 머리 오른쪽 ⋮ 하나("{항목 이름} 더보기") → Menu(1280 미만 Menu Sheet). 수정 · 삭제 아이콘을 줄마다 늘 늘어놓지 않는다(2026-10-25 사용자 결정 — 2026-10-02 의 "데스크톱 줄의 동작은 줄 끝 ⋮ + Menu" 를 고쳤다).
  • 줄에 ⋮ 를 두는 자리는 콘텐츠가 높은 카드 머리뿐 — 사진 · 여러 줄 · 버튼이 든 카드 하나가 항목 하나일 때. 데스크톱 데이터 표의 줄 끝 ⋮ 는 이 규칙 밖이다 — 그루 이음 관리 화면 차례에 다시 보고, 그때까지 Table 스펙의 지금 문장을 따른다.
  • 폰 스와이프는 지름길 — 같은 동작은 줄을 눌러 들어간 화면에 다 둔다(키보드 · 스크린리더의 길).
  • 비모달 Menu — 뒤 화면을 숨기지 않는다. Tab · 바깥 누르기로 나가면 닫히고, 고르면 실행하고 닫혀 초점은 트리거로.
  • 툴팁은 마우스(200 / 100ms) · 키보드(바로)의 보조 — 이름은 aria-label, 막힌 이유는 가까운 글, 네이티브 title 은 쓰지 않는다. 폰에서도 읽어야 하는 설명은 Help Bubble.
  • 글 — 메뉴 줄은 동사로 짧게(2 ~ 6자), 툴팁 · 말풍선은 해요체 · 문장이면 마침표.

접근성

  • Menu: 트리거 aria-haspopup="menu" · aria-expanded, role="menu" · menuitem · group. 키보드 위치는 링으로(바탕색만으로 알리지 않는다).
  • Menu Sheet: role="dialog" + aria-modal, 줄은 <button>. 보이지 않는 "닫기" 는 키보드 초점이 오면 보인다.
  • Help Bubble: role="dialog"(비모달) + 제목 aria-labelledby. Tooltip: role="tooltip" + 트리거 aria-describedby, WCAG 1.4.13(말풍선 위로 옮겨도 남는다 · Esc).

Tabs · Segmented Control

수치 · 규칙의 원본은 specs/components/tabs.md · tabs.yaml · chip-tabs.yaml 과 segmented-control.md · segmented-control.yaml 이다 — 2026-10-02 SEED Tabs · Segmented Control 구조로 새로 정했다(옛 variant 넷 · 수동 활성화를 걷었다). 이 절은 토큰과 닿는 자리만 모은다.

나누기

자리컴포넌트
다른 구역 · 페이지로 옮긴다(1차, 화면 · 구역 맨 위)Tabs — Line
1차 탭 안에서 다시 나눈다(2차)Tabs — Chip Tabs(필터 바가 같은 화면에 있으면 Line)
같은 내용 2 ~ 4가지 거르기 · 정렬 · 보기(그 내용 바로 위, 한 화면 하나)Segmented Control
2 ~ 4개 짧은 폼 값 · 목록 조건Chip(하나 고르기 · 필터 바)

Line

요소값
크기small 40 · 글 t4 14(기본) · medium 44 · 글 t5 16. 탭 위아래 · 좌우 10, 글은 아래로 붙인다. 글은 고르든 안 고르든 700
색안 고름 fg-neutral-subtle, 고름 fg-neutral + 아래 2px fg-neutral 막대(motion-duration-d4 · motion-ease-easing 로 미끄러진다). 브랜드 색 · 굵기 변화 없음 — Desk · HR 이 같다
목록bg-layer-default + 바닥 안쪽 1px stroke-neutral-subtle
폭Fill — 5개 이하 · 짧은 글, 칸을 나누고 막대를 좌우 16 들인다. Hug — 6개 이상 · 긴 글 · 넓은 데스크톱 자리, 목록 좌우 16 · 넘치면 가로 스크롤(고른 탭으로 16 여유를 두고 스크롤)
누름 · 포커스 · 비활성탭 2px 거리 축소만(색 · 호버 모양 없음) · 탭 안쪽 링 2px · 글 fg-disabled
알림 점Notification Badge small — 6 · 브랜드 글자색(브랜드 파일의 fg-brand, 다크에서 밝은 짝), 글 끝 2 · 줄 상자 위 — 새 소식이 있는 탭 하나에만

Chip Tabs

칩 하나는 Chip(chip.yaml)의 Solid · Outline Strong 그대로다 — medium 36(기본) · large 40, 고르면 bg-neutral-inverted · fg-neutral-inverted. 목록은 좌우 spacing-global-gutter · 위아래 8 · 칩 사이 spacing-between-chips, 한 줄 가로 스크롤. 화면 전체 내용을 바꾸면 Solid, 일부면 Outline.

Segmented Control

요소값
크기트랙 안쪽 4 + 칸 34 = 42, 글 t5 16 · 700, 칸 좌우 12 — 칸이 트랙 폭을 똑같이 나눈다(최소 폭 없음 — 폰에서도 4개)
색트랙 bg-neutral-weak-alpha(투명 — 회색 바닥 위에서도 보인다, v120), 안 고른 글 fg-neutral-subtle, 고른 칸은 흰 알약 bg-layer-default + 안쪽 짙은 1px stroke-neutral-contrast 위 fg-neutral(motion-duration-d4 로 미끄러진다 — SEED 의 옅은 1px 은 트랙과 1.14:1 이라 바꿨다)
누름 · 호버안 고름 bg-neutral-weak-pressed + 1px stroke-neutral-weak(글 fg-neutral-muted) · 고름 bg-layer-default-pressed + 짙은 1px 그대로, 칸 안의 글만 2px 거리 축소
비활성글 fg-disabled, 고른 채 막히면 칸에 bg-disabled + 1px stroke-neutral-solid(흐림 없음 — v106)

쓰는 규칙

  • 화살표로 옮기면 바로 고른다(자동) — 바로 저장되거나 되돌리기 어려운 값은 탭 · Segmented 에 두지 않는다(폼 값은 Chip · Select).
  • 탭 내용은 바로 바꾸고 탭마다 상태(스크롤 · 입력)를 남긴다. 폰의 1차 탭만 밀어 넘기고, 웹은 1차 탭을 주소에 남긴다.
  • 탭 · Segmented 글에 개수를 붙이지 않는다 — 새 소식은 한 탭에 알림 점.

Accessibility 체크리스트

  • Tabs — tablist(보이는 제목 또는 aria-label) · tab(aria-selected · aria-controls) · tabpanel(aria-labelledby), 고른 탭만 tabindex="0", ← → · Home · End 로 옮기며 고른다(끝에서 처음으로, 막힌 탭은 건너뛴다)
  • Segmented Control — radiogroup(aria-label) + 라디오, 화살표로 옮기며 고른다
  • 알림 점은 보조 기술에 "새 소식" 을 덧붙인다
  • 키보드 포커스 링 — Line 은 탭 안쪽, Chip Tabs · Segmented 는 바깥
  • 누르는 높이 — Line small 40 · Segmented 34 는 AAA(44)에 못 미친다(AA ✓)

Switch / Checkbox / Radio (control 묶음)

binary on/off 상태 또는 group 선택을 표현하는 form control 3종. 공통 a11y 베이스 + 시맨틱 차이.

의미 차이

Component의미변경 시점
Switch즉시 적용되는 토글 (on/off)누르는 순간 적용 (e.g. 알림 켜기/끄기)
Checkbox다중 선택 또는 단일 confirmform submit 시점 또는 즉시 적용
Radio그룹 내 단일 선택form submit 또는 즉시

선택 기준: 즉시 적용 + on/off → Switch, 다중 선택 + form → Checkbox, 단일 선택 + group → Radio. UI 혼동 회피를 위해 의미별 명확히 분기. Switch 는 누르는 순간 적용될 때만 쓴다 — 저장 · 실행을 눌러야 적용되는 켜고 끄기는 Checkbox 다(2026-09-30 사용자 결정 — SEED 와 같다). 누르면 화면이 바로 바뀌는 것(일정의 "종일")은 값이 저장 때 들어가더라도 Switch.

Spec 공통 (신규 토큰 없음)

세 컨트롤 모두 2026-09-30 SEED 구조로 바뀌었다(아래 Switch · Checkbox · Radio, specs/components/switch.md · checkbox.md · radio-group.md). 색 규칙은 셋이 같다(사용자 결정).

요소값
선택 · 켜짐 채움bg-neutral-inverted(짙은 회색)가 기본. 브랜드 채움은 tone="brand" 일 때만 — 서비스 핵심 흐름
선택 · 켜짐 표시(체크 · 점 · 엄지)fg-neutral-inverted. tone="brand" 면 static-white
선택 안 됨 · 꺼짐stroke-neutral-solid(표면과 3:1 이상, v109) — Checkbox · Radio 는 1px 테두리, Switch 는 트랙 채움
disabled전용 색(v106 — State 절), 불투명도로 흐리게 하지 않는다. 선택 · 켜진 채 막히면 모양 그대로 회색 — Checkbox · Radio 는 bg-disabled 채움 + fg-disabled 표시, Switch 는 fg-disabled 트랙 + bg-disabled 엄지. cursor:not-allowed
hoverCheckbox · Radio 는 누름 색. Switch 는 색이 바뀌지 않는다 — 켜짐 색이 상태를 뜻해서(v104)
pressed칸 · 동그라미 · 스위치만 세로 2px 거리 축소(v104)
focus키보드 포커스에만 링 2px · 띄움 2px(v106)

Switch

상세 spec(Anatomy / Sizes / States / Motion / Accessibility / Do-Don't)은 specs/components/switch.md가 단일 SoT. 코드(recipes/shadcn/components/ui/switch.tsx) · 예제(recipes/shadcn/examples/switch-examples.mjs) · preview 4 source 동기.

  • 구조: 스위치(Switchmark — 트랙 + 엄지) · 스위치 + 라벨(Switch) — SEED Switch(2026-09-30).
  • 크기(이름은 트랙 높이): 16 트랙 26 × 16 · 엄지 12 · 라벨 13 / 24 38 × 24 · 20 · 14(기본) / 32 52 × 32 · 26 · 16. 트랙 · 엄지 모서리 radius-full.
  • 끄면 엄지가 0.8 로 작아진다 — 색 말고도 자리 · 크기로 켬 · 끔이 갈린다. 엄지에 그림자는 없다.
  • 톤: neutral(짙은 회색, 기본) · brand.
  • 모션: 엄지의 이동 · 크기 motion-duration-d3 (150ms), 색은 20ms 뒤에 motion-duration-d1 (50ms) — 둘 다 motion-ease-easing. 누르면 스위치만 세로 2px 거리 축소(색은 그대로).
  • 누르는 순간 적용되는 설정에만 쓴다 — 저장해야 적용되는 값은 Checkbox.
  • "라벨 왼쪽 · 스위치 오른쪽" 설정 줄(제목 · 설명 · 아이콘)은 List 의 스위치 줄(ListSwitchItem — 아래 List)이다. 그 줄에는 스위치 32 만(Switchmark) 끼우고 줄 전체가 누르는 영역이다 — 줄을 누르면 콘텐츠가 함께 줄고 스위치는 따로 줄지 않는다.
  • 터치 타겟은 스위치 단독으론 작음(높이 16 · 24 · 32). 반드시 라벨까지 묶어 44 확보(WCAG 2.5.5 AAA) — 설정 줄에 스위치만 넣으면 줄 전체.

Checkbox

상세 spec(Anatomy / Sizes / States / Motion / Accessibility / Do-Don't)은 specs/components/checkbox.md가 단일 SoT. 코드(recipes/shadcn/components/ui/checkbox.tsx) · 예제(recipes/shadcn/examples/checkbox-examples.mjs) · preview 4 source 동기.

  • 구조: 칸(Checkmark) · 칸 + 라벨(Checkbox) · 묶음(Checkbox Group) — SEED Checkbox(2026-09-30).
  • 크기: medium 칸 20 · 라벨 14 · 줄 32(기본) / large 24 · 16 · 36. 모서리 radius-r1 (4px).
  • 모양: square(칸 + 체크, 기본) · ghost(칸 없이 체크만 — 필수가 아니고 셋 이하). 톤: neutral(짙은 회색, 기본) · brand.
  • 일부 선택(indeterminate): 가로줄 — 부모 · 자식 묶음에서 자식을 일부만 골랐을 때.
  • 터치 타겟은 칸 단독으론 작음(20 · 24). 반드시 라벨까지 묶어 44 확보(WCAG 2.5.5 AAA) — 목록 행에 칸만 넣으면 행 전체.
  • 오류는 칸을 바꾸지 않는다 — 묶음 아래 글로 알린다.

Radio

상세 spec(Anatomy / Sizes / States / Motion / Accessibility / Do-Don't)은 specs/components/radio-group.md가 단일 SoT. 코드(recipes/shadcn/components/ui/radio-group.tsx) · 예제(recipes/shadcn/examples/radio-group-examples.mjs) · preview 4 source 동기.

  • 구조: 동그라미(Radiomark) · 동그라미 + 라벨(Radio) · 묶음(Radio Group) — SEED Radio(2026-09-30).
  • 크기: medium 동그라미 20 · 점 8 · 라벨 14 · 줄 32(기본) / large 24 · 10 · 16 · 36. 모서리 radius-full.
  • 선택: 테두리 없이 채운 원 + 가운데 점. 톤: neutral(짙은 회색, 기본) · brand.
  • 묶음은 세로로만 쌓는다(줄 사이 12 — 줄마다 누르는 영역 44 를 온전히 받게, SEED 는 4) — 짧은 선택지를 한 줄에서 고르게 하려면 Segmented · Chip.
  • 설명 · 딸린 입력이 붙는 선택지는 Radio 가 아니라 Select Box(아래 Select Box).
  • 오류는 동그라미를 바꾸지 않는다 — 묶음 아래 글로 알린다.

Layout

  • label 위치: control 우측 (LTR) — control과 label 간 sm (8px) 간격
  • 그룹 spacing:
    • vertical group: 항목 간 md (12px) ~ lg (16px) — Checkbox · Radio 묶음은 줄 최소 높이 32 · 36 에 줄 사이 12(specs/components/checkbox.yaml · radio-group.yaml — 줄마다 누르는 영역 44 를 온전히 받는다, 사용자 결정 2026-09-30. SEED 는 4)
    • horizontal group: 항목 간 lg (16px) — Radio 는 가로로 놓지 않는다(2026-09-30)
  • group label (group 제목): control 위 caption + xs 간격

Touch target (WCAG 2.5.5)

  • control 자체는 작음(Radio 동그라미 · Checkbox 칸 20 · 24, Switch 트랙 높이 16 · 24 · 32) — 반드시 label까지 포함한 hit area가 44×44px 이상 확보 필수
  • label 클릭으로도 toggle/select 가능 (<label for="..."> 또는 control wrap)

Accessibility

  • HTML: <input type="checkbox|radio"> + <label for="..."> 사용 — native a11y 자동
    • Switch는 HTML native 없음 → <input type="checkbox" role="switch"> 또는 role="switch" + aria-checked. 스위치만 쓰는 설정 줄은 줄의 제목이 스위치의 이름이 되게 <label> 로 감싸거나 aria-labelledby 로 잇는다
  • focus ring: control 외곽 + label 영역 모두 focus indicator 표시 (border-focus 2px outline)
  • aria 상태:
    • Checkbox: aria-checked="true|false|mixed" (mixed = indeterminate)
    • Radio: group은 role="radiogroup" + aria-labelledby="group-title"
    • Switch: role="switch" + aria-checked (또는 native checkbox + role="switch")
  • 키보드:
    • Checkbox/Switch: Space로 toggle (Switch 는 Enter 도)
    • Radio: arrow keys (↑/↓ 또는 ←/→)로 group 내 이동, 선택 즉시
    • Tab으로 group 진입 → 첫 번째 또는 현재 선택값으로 focus
  • disabled 상태: control + label 모두 disabled 표시 + 1.4.3 incidental
  • error 상태 (form validation 실패): Checkbox · Radio 는 칸 · 동그라미를 바꾸지 않고 묶음 아래 글로(2026-09-30). Switch 에는 오류 상태가 없다 — 누르는 순간 적용되므로 검증할 값이 없고, 저장에 실패하면 스위치를 되돌리고 무엇이 안 됐는지 알린다

List

상세 spec(Anatomy / 줄의 종류 / 상태 / 모션 / Accessibility / Do-Don't)은 specs/components/list.md가 단일 SoT, 수치는 list.yaml · list-header.yaml. 코드(recipes/shadcn/components/ui/list.tsx) · 예제(recipes/shadcn/examples/list-examples.mjs) · preview 4 source 동기.

  • 구조: 목록(List) · 한 줄(List Item) · 목록 제목(List Header) · 줄 사이 선(ListDivider) — SEED List(2026-10-01). 설정 · 메뉴 · 선택 · 키-값 줄과 거래 · 할 일 · 알림 같은 내용 줄을 모두 List 로 그린다. RadioList 는 걷었다 — 하나 고르기는 오른쪽 라디오 줄(ListRadioItem).
  • 한 줄: 위아래 spacing-x3 (12) · 좌우 spacing-global-gutter (24) · 제목 t5 16 · 400 fg-neutral · 설명 t3 13 fg-neutral-subtle(제목 아래 2) — 한 줄 46 · 두 줄 66.
  • 앞: 설정 · 메뉴 줄은 아이콘 22(fg-neutral), 색이 뜻을 가진 내용 줄은 타일 40(모서리 radius-r3 12 · chart-{색}-weak 바탕 · 아이콘 20 — 아이콘이 없으면 태그 아이콘, 이체 줄은 회색). 은행 · 카드 같은 물건 줄은 로고 타일 40(Logo Tile), 카드 혜택 줄은 카드 그림 56(Image Frame). 체크 · 라디오는 24, 스위치는 32.
  • 뒤: 값 글자(t5 · fg-neutral-subtle) · 오른쪽 화살표 18(화면을 옮기는 줄에만) · 컨트롤 · 작은 버튼.
  • 누름 · 호버(웹): 바탕 층이 좌우 6 들어와 모서리 10 의 bg-layer-default-pressed 가 되고, 콘텐츠 층만 2px 거리로 준다(v104). 끼운 컨트롤은 따로 줄지 않는다. 포커스 링은 줄 안쪽 2px.
  • 강조: 바탕만 옅은 브랜드 색(브랜드 파일의 brand-weak 역할 색 — 누름 · 호버는 한 단계 짙은 짝, 그동안 설명 · 값 글자는 fg-neutral-muted 로 4.5:1 을 지킨다).
  • 줄 사이 선은 기본 없음 — 필요할 때만 ListDivider(1px stroke-neutral-subtle, 줄 폭 또는 좌우 24 들임).
  • 목록 제목: t4 14 · 위아래 8 · 좌우 24 — mediumWeak(500 · fg-neutral-subtle, 기본) · boldSolid(700 · fg-neutral).
  • 하위 줄(2026-10-10): 부모 · 하위 두 단계에서 줄은 편집을 열고 하위만 접는 목록(카테고리) — 부모 줄 앞 꺾쇠 단추 44(이름 "{카테고리} 하위 카테고리" + aria-expanded · 펼치면 90° · 300ms) · 하위 줄은 부모 제목 자리 104 · 하위가 없는 줄도 꺾쇠 자리를 비워 부모 타일이 한 세로줄(52)에 선다(17B). 여러 단계에서 고르는 나무는 Tree View.
  • 목록은 흰 바탕(bg-layer-default) · 시트(bg-layer-floating) 위에 둔다 — 회색 바탕(bg-layer-basement) 위에서는 누름 바탕이 보이지 않는다(카드에 담는다).

Select Box

상세 spec(Anatomy / 컨트롤 / 배치 / 상태 / 펼침 / 모션 / Accessibility / Do-Don't)은 specs/components/select-box.md가 단일 SoT, 수치는 select-box.yaml. 코드(recipes/shadcn/components/ui/select-box.tsx) · 예제(recipes/shadcn/examples/select-box-examples.mjs) · preview 4 source 동기.

  • 구조: 하나 고르기(Radio Select Box) · 여럿 고르기(Check Select Box) · 묶음(Select Box Group) — SEED Select Box(2026-10-01). 설명 · 아이콘 · 딸린 입력이 붙는 선택지 2 ~ 6개를 견줘 고르고, 저장 · 다음 같은 버튼으로 반영한다. Tile 은 걷었다.
  • 상자: 모서리 radius-r3 (12) · 안쪽 1px stroke-neutral-weak. 고르면 안쪽에 2px stroke-neutral-contrast(v113)를 덧그린다 — 내용이 밀리지 않고, 바탕은 그대로다(브랜드 색 없음).
  • 글자: 제목 t5 16 · 500 fg-neutral · 설명 t3 13 fg-neutral-muted(두 줄까지). 앞 아이콘 22(fg-neutral).
  • 컨트롤은 오른쪽 — 라디오 20(neutral) · 칸 없는 체크(Checkbox Ghost) · 없음(테두리만, 좁은 3열 같은 자리). 컨트롤은 따로 줄지 않고 자기 포커스 링도 그리지 않는다.
  • 배치: 1열은 가로형(위아래 16 · 왼쪽 20 · 오른쪽 16, 세로 가운데), 2 ~ 3열은 세로형(위아래 20 · 좌우 16, 앞이 위 · 컨트롤은 위 오른쪽). 묶음 줄 사이 spacing-component-default · 열 사이 12, 2열 이상이면 모든 상자가 가장 긴 상자의 높이다. 가장 작은 상자 54.
  • 누름 · 호버(웹): 상자 바탕이 bg-layer-default-pressed 가 되고 누르는 자리(콘텐츠 + 컨트롤)만 2px 거리로 준다(v104). 키보드 포커스 링은 상자 바깥 2px · 띄움 2px.
  • 펼침: 고른 상자 아래로 딸린 입력 · 안내가 열린다(안쪽 좌우 20 · 아래 16, 높이 400ms · 투명도 300ms). 닫히면 보이지 않고 Tab 도 닿지 않는다.
  • 누르는 순간 바뀌는 고르기(테마 같은)는 List 의 라디오 줄, 누르면 바로 무언가를 하는 자리는 버튼이다.
  • 권한을 주는 여럿 고르기(HR 사용자 역할)도 상자로 고르고 "저장" 한 번으로 반영한다 — 폰 · 데스크톱 같은 모양(2026-10-15 마무리 10A, 위 "마무리" 절).

Avatar · Avatar Stack

2026-10-03 SEED Avatar · Avatar Stack 구조로 다시 정했다(사용자 결정 — 비교 페이지 https://claude.ai/artifact/4ySVacsdnG4fgraR1HRK3G, 5C · 6B). 수치 원본은 specs/components/avatar.yaml · avatar-stack.yaml, 쓰는 규칙은 avatar.md 다. 옛 Avatar v58 절(24 · 32 · 40 · 56 · 사각 변형 · 최대 3 + "+N more" · 호버 축소 · 상태 점)은 걷었다 — 옛 스펙은 specs/components/avatar.history/v-pre-seed-display.*. 머리말의 avatar 대비 쌍(chart-blue × 흰 글자)은 라이트 이니셜 하나를 잰다.

AvatarAvatar Stack
크기20 · 24 · 36 · 42 · 48 · 56 · 64 · 80 · 96 · 108 — 자리마다 대표 크기(한 줄 목록 36 · 두 줄 목록 42 · 줄 안 묶음 24 · Desk 계정 머리 80 · HR 큰 사진 96 · 프로필 수정 108)같은 10단계 — 묶음이 정하고 안의 아바타가 모두 따른다
모양원 하나 · 1px 안쪽 stroke-neutral-overlay(투명 — v118, 모든 크기)지름 1/4 겹침(−5 ~ −27) · 놓인 바탕색 링 1 ~ 5(bg-layer-default, 시트 안은 bg-layer-floating) · 뒤가 위
사진이 없을 때이니셜 + 이름 색 — 차트 10색(v110) 바탕, 글자 fg-neutral-inverted 700(지름의 40%, 가장 작아도 10)앞 4명 + "+N" 원(같은 크기 · bg-neutral-weak + fg-neutral-muted 700)
  • 이니셜 = 표시 이름의 첫 글자 하나(로마자는 대문자 — "Kim Minsu" → "K"). 이름 색 = 표시 이름의 유니코드 코드 포인트 합 % 10 → blue · green · orange · violet · pink · indigo · red · yellow · brown · gray(v110 순서) — 웹 · 앱이 같다("김민수" → blue · "이서연" → brown · "Kim Minsu" → indigo). 대비 라이트 4.55 ~ 5.50 · 다크 6.07 ~ 7.70:1 — 다크에서 흰 글자는 2.4:1 이라 쓰지 않는다.
  • 사람만 아바타다 — 은행 · 증권 · 카드 같은 물건은 Logo Tile, 카테고리는 List 의 타일이다("이미지" 절). 주식 타일은 증권 화면 차례에 정한다.
  • 이름 옆 아바타는 장식(이름을 한 번만 읽는다), 혼자면 이름을 가진다. 상태(안 낸 사람)는 흐리게 하지 않고 배지 · 글로.

날짜 · 시각 고르기 — Date Picker · Time Picker · Wheel Picker

2026-10-03 SEED 구조로 새로 정했다(옛 Calendar v61 · Date Range Picker v72 · Time Picker v72 를 대신). 수치 원본은 specs/components/date-picker.yaml · time-picker.yaml · wheel-picker.yaml, 쓰는 규칙은 같은 이름의 .md. 옛 Calendar 스펙은 specs/components/calendar.history/v-pre-seed-date.*.

날짜 · 시각은 치지 않고 고른다 — 칸은 Input Button 이고, 누르면 1280 미만은 아래 시트 · 이상은 칸 아래 팝오버가 열리며 "완료" 로 넣는다(고르는 동안 칸 값은 그대로, 닫으면 버림).

이런 값고르는 것
날짜 하나Date Picker — 한 달, 늘 6주
기간Date Picker 기간 — 칸 하나("9월 28일~10월 6일"), 시트는 이어지는 달 · 팝오버는 두 달, 위에 빠른 기간 칩
여러 날Date Picker 여러 날 — 따로 그린 원
시각Time Picker — 오전·오후 → 시 → 분, 분 간격 기본 5
날짜 + 시각날짜 칸 + 시각 칸 나란히
달만(예산 · 홈 · 카드 실적)Wheel Picker 연 · 월 + "완료"
1 ~ 31(매월 N일 · 결제일)Select
Date PickerTime Picker · Wheel Picker
크기칸 48(폭 ÷ 7) · 원 42 · 머리 · 요일 48 · 늘 6주 · 팝오버 336 · 두 달 696항목 44 × 5 = 220 · 연 · 월 휠 7칸 · small 36
글자숫자 t5 500 fg-neutral-muted · 요일 t4 500 fg-neutral-subtle · 제목 t5 700항목 26 / 35 · 500 — 고른 것 fg-neutral · 둘레 fg-disabled
상태오늘 옅은 원 bg-neutral-weak + 숫자 700 · 고름 bg-neutral-inverted · 기간 띠 bg-neutral-weak · 앞뒤 달 fg-disabled(누르지 못함) · 막힘 fg-disabled + 취소선 · 읽기 전용 stroke-neutral-solid띠 bg-neutral-weak 모서리 8 · 좌우 16 들임 · 안개 min(40%, 3칸)
키보드WAI-ARIA Grid — ←→ 하루 · ↑↓ 한 주 · PageUp/Down 한 달 · Shift+Page 한 해칼럼마다 Tab · ↑↓ · Home · End
칸 표기올해 "10월 15일 (목)" · 다른 해 "2027년 1월 3일 (일)" · 기간 물결표"오후 3:00"

빠른 기간은 한 벌이다 — 이번 주(일 ~ 토) · 이번 달(1일 ~ 말일) · 지난 달 · 최근 7일 · 30일 · 최근 3개월 · 6개월 · 1년(이번 달을 넣은 달들) · 올해(1월 1일 ~ 12월 31일). 화면은 이 안에서 고른다.

Field (폼 — 라벨 · 설명 · 오류)

수치 · 규칙의 원본은 specs/components/field.md · field.yaml 이다 — 2026-10-01 SEED Field 구조로 정했다. 옛 Label · Form 스펙과 v62 Form layout · v75 Form validation 의 규칙을 여기로 합쳤다(옛 글은 바로 앞 백업 DESIGN.history/v114-korean-line-break.md 의 Form layout · Form validation 절, 옛 스펙은 specs/components/label.history/ · form.history/). 이 절은 토큰과 닿는 자리만 모은다.

짜임

Field 는 머리(라벨 · 필수 점 또는 "선택" · 보조 액션) · 입력 · 꼬리(설명 또는 오류 · 글자 수)를 8 간격으로 쌓는다. 머리 · 꼬리는 좌우로 2 들어온다. 입력은 Text Input · Textarea · Select · Input Button · Checkbox · Radio · Select Box 묶음이고, 2026-10-09 부터 Slider(머리 오른쪽에 지금 값) · Input OTP · Color Swatch 묶음 · Icon Picker 도 감싼다.

부위값
라벨t5 16px · 500(bold 700) · fg-neutral — 오류여도 그대로
필수 점6px(0.375rem) fg-critical — 라벨 끝, 위 4 · 왼쪽 2. 화면 읽기 프로그램에는 숨기고 칸의 aria-required 로 알린다
"선택"t4 14px · 줄 높이 22 · fg-neutral-subtle
설명t4 14px fg-neutral-subtle(앞 아이콘 16 은 선택)
오류t4 14px fg-critical + 아이콘 16 — 설명 자리를 대신한다
글자 수t4 14px — 쓴 수 fg-neutral(비면 fg-neutral-subtle), 최대 fg-neutral-subtle, 오류면 둘 다 fg-critical
폼Field 사이 spacing-x6 (24px) · 나란히 둔 두 칸 사이 spacing-x4 (16px, 768 미만은 한 줄에 하나)

대비(라이트 · 다크): 라벨 16.41 · 13.42, 설명 · "선택" 5.50 · 6.09(시트 다크 5.27), 오류 5.06 · 6.08(시트 다크 5.27).

규칙

  • 필수 표시는 2/3 규칙 — 한 화면 칸의 2/3 이상이 필수면 선택 칸에만 "선택", 아니면 필수 칸에만 점. 한 폼에 섞지 않는다. 칸이 하나뿐이면 붙이지 않는다.
  • 라벨은 칸 위에 둔다 — 왼쪽 라벨 배치(옛 horizontal)는 두지 않는다. 라벨은 명사형, 마침표 없이.
  • 오류 글은 무엇을 하면 되는지 짧게(Writing — 해요체 · 마침표) — "휴대폰 번호 10~11자리로 입력해주세요.". 맞음 · 확인 중은 설명 자리에 글로 — 초록 테두리 · 돌림 표시를 두지 않는다.
  • 묶음(Checkbox · Radio · Select Box)의 칸 이름 · 오류도 Field 가 그린다 — 라벨이 묶음의 이름(aria-labelledby)이다.
  • 오류가 생기면 화면 밖 알림 자리(aria-live="polite")가 한 번 읽는다.

검증과 나가기

  • 저장 · 신청 버튼은 켜 둔다. 누르면 비거나 틀린 칸마다 오류를 보이고 첫 오류 칸으로 포커스를 옮긴다(제출 시 검증 — 기본). 다 채울 때까지 버튼을 끄지 않는다.
  • 잘못 넣으면 위험한 칸(보안 · 금융 — 비밀번호 확인 · 계좌번호 · 송금액)만 칸을 떠날 때 바로 알린다. 입력하는 동안 글자마다 오류를 띄우지 않는다.
  • 서버 확인(아이디 중복)은 칸을 떠난 뒤 — 확인하는 동안 설명 자리에 "확인하는 중…", 결과도 설명 · 오류 자리에. 늦게 온 옛 응답이 새 응답을 덮지 않게 이전 요청을 취소한다.
  • 작성 · 수정 화면에서 값이 바뀐 채 나가려 하면(뒤로 · 닫기 · 바깥 누름 · 시트 끌어내림) "작성한 내용이 사라져요" 를 묻는다(Alert Dialog). 바뀐 값이 없거나 자동 저장이면 묻지 않는다.

오류 글 꼴(v75 에서 옮겨 Writing 에 맞췄다)

규칙오류 글
필수"{칸 이름}을(를) 입력해주세요." · 고르는 칸은 "{칸 이름}을(를) 골라주세요."
최소 · 최대 길이"{N}자 이상 입력해주세요." · "{N}자 이내로 입력해주세요."
숫자 범위"{N} 이상으로 입력해주세요." · "{N} 이하로 입력해주세요."
형식"{칸 이름}을(를) {형식}으로 입력해주세요."(예: "휴대폰 번호 10~11자리로 입력해주세요.")
이메일"이메일 주소를 확인해주세요(예: [email protected])."
다시 입력"비밀번호가 서로 달라요."
서버 확인"이미 쓰고 있는 {칸 이름}이에요."

{칸 이름} 은 라벨과 같게 쓴다 — 오류만 보고도 어느 칸인지 안다.

기다림 — Skeleton · Progress Circle · Progress · Content Placeholder · Scroll Fog

2026-10-03 SEED Skeleton · Progress Circle · Pull To Refresh · Content Placeholder · Scroll Fog 와 Loading 패턴의 시간표로 새로 정했다(사용자 결정 — 비교 페이지 https://claude.ai/artifact/4ySVacsdnG4fgraR1HRK3G). 옛 Skeleton / Loading(v63) · Spinner / Progress(v67) 절을 대신한다. 수치 원본은 specs/components/skeleton.yaml · progress-circle.yaml · pull-to-refresh.yaml · progress.yaml · content-placeholder.yaml · scroll-fog.yaml, 쓰는 규칙은 같은 이름의 .md(당겨서 새로 고침은 progress-circle.md). 옛 스펙은 skeleton.history · spinner.history · progress.history 의 v-pre-seed-loading.*. 토큰은 더하지 않았다 — v104 의 gradient-shimmer-neutral · gradient-fade-mask · motion-duration-loop · motion-ease-easing 을 쓴다.

나누기

이런 때쓰는 것
목록 · 카드 · 상세를 처음 불러옴Skeleton — 틀은 그리고 데이터 자리만
섹션 새로 고침 · 목록 끝 더 불러오기 · 구조를 그릴 수 없는 화면Progress Circle — 요소 안 24 · 콘텐츠 가운데 40
저장 · 제출Button 의 로딩(원 14 · 14 · 16 · 18)
올리기 · 받기값 있는 Progress Circle 24
앱 목록 · 대시보드를 다시 받음당겨서 새로 고침 — 원판 없는 원 24
예산 · 목표가 얼마나 찼나Progress — 막대(미터)
이미지가 없거나 못 불러옴Content Placeholder — Image Frame 이 대체 그림으로 그린다(불러오는 동안은 같은 모서리의 Skeleton, "이미지" 절)
스크롤 영역에 더 있음Scroll Fog

시간표 — 1초 · 5초 · 10초

모든 불러오기가 따른다 — 1초 안에 오면 아무것도 보이지 않고(틀만), 1초부터 스켈레톤 · 원, 5초에 "평소보다 오래 걸리고 있어요.", 10초에 실패(Result Section + "다시 시도"). 요청 제한은 10초이고 저절로 다시 시도하는 것(읽기만)은 그 안에서만이다. 달 · 기간을 바꾸면 머리는 바로 바뀌고 바뀔 숫자 · 목록 자리만 기다린다 — 옛 달 숫자는 지운다. 같은 내용을 다시 받으면 보던 내용을 지우지 않는다(Result Section). 원본은 specs/components/skeleton.md 의 "기다리는 동안" 한 곳이다.

모양

SkeletonProgress CircleProgressContent PlaceholderScroll Fog
크기내용의 크기 · 글은 그 글자의 줄 높이(14 → 19)24(두께 3) · 40(두께 5) · 버튼 안은 Button높이 8틀을 채움 · 그림 = 틀 높이의 50%(16 ~ 160)기본 20 · 가로 좌우 20 · 세로 위 20 · 아래 80
모양모서리 글 8 · 그림 자리 4 · 6 · 8(Image Frame 대로) · 타일 12 · 카드 면 16 · 아바타 full · 화면 폭 사진 0끝이 둥근 호 · 12시 시작모서리 full제 모서리 없음마스크 — 색이 없다
색면 bg-neutral-weak + 흰 띠 gradient-shimmer-neutral(다크 짝)원 stroke-neutral-solid · 트랙 stroke-neutral-subtle, 톤 brand · staticWhite · inherit트랙 bg-neutral-weak · 채움 브랜드 글자색(넘친 한도만 fg-critical)면 bg-neutral-weak · 그림 stroke-neutral-weakgradient-fade-mask
움직임반짝임 motion-duration-loop · motion-ease-easing1.2초 회전 + 호 · 채움 300ms채움 300ms없음없음 — 늘 켜짐
모션 줄이기띠가 멈춘다돌지 않는 3/4 호바로 바뀐다——

쓰는 규칙

  • 틀(머리 · 탭 · 제목 · 버튼 · 카드 면)은 처음부터 그린다 — 화면을 덮는 회색 막 "Loading" · 틀 없는 화면 가운데 원은 두지 않는다.
  • 스켈레톤은 흰 면(bg-layer-default · bg-layer-floating) 위에만 — 페이지 바탕(bg-layer-basement) 위에서는 같은 색이라 사라진다(1.00:1). 깜빡임(펄스)은 두지 않는다.
  • 스켈레톤과 원을 한 자리에 같이 쓰지 않는다.
  • 막대는 미터다 — 기다림 · 올리기에 쓰지 않는다. 높이 · 색은 하나이고 주의 구간 색 · 달성 색은 없다(달성은 글자 "달성").
  • 끝 흐림은 늘 켜 두고 흐린 쪽에 깊이만큼 여백을 둔다 — 시트 · 대화상자의 "넘칠 때만 아래 48"(2026-10-02)은 이것으로 바뀌었다.
  • 깨진 이미지 아이콘 · 빈 이미지 칸을 두지 않는다.

접근성

  • 기다리는 영역에 aria-busy, 화면에 상태 글 하나(role="status") — "불러오는 중…" · "평소보다 오래 걸리고 있어요." 를 한 번씩 읽는다. 결과는 Result Section 이 알린다.
  • Progress Circle 은 role="progressbar" — 이름 "불러오는 중", 값 글 "40%"(영어 · 세 점을 쓰지 않는다). Progress 는 role="meter" — 이름 "식비 예산 400,000원 중 350,000원".
  • 스켈레톤 · 끝 흐림 · 대체 그림의 아이콘은 장식이다.

이미지 — Image Frame · Aspect Ratio · Logo Tile

2026-10-04 SEED Image Frame · Aspect Ratio 와 groo 의 물건 타일 · 카드 그림 규칙으로 새로 정했다(사용자 결정 — 비교 페이지 https://claude.ai/artifact/G351nuKcYX2xhorvA5UD6X, 1A · 2A · 3A · 4B · 5A · 6B · 7A · 8A · "따라오는 것"). 수치 원본은 specs/components/image-frame.yaml · card-art.yaml · aspect-ratio.yaml · logo-tile.yaml, 기관 색은 institution-colors.yaml, 쓰는 규칙은 image-frame.md · aspect-ratio.md · logo-tile.md. 옛 Aspect Ratio(v72) · Carousel(v71) 절은 걷었다 — 옛 스펙은 specs/components/aspect-ratio.history · carousel.history 의 v-pre-seed-image.*. 토큰은 v118 의 stroke-neutral-overlay 하나를 더했다(이미지 위 투명 윤곽 — Avatar 의 테두리도 이 색).

나누기

보이려는 것쓰는 것
사람Avatar — 원, 사진 또는 이니셜 + 이름 색
은행 · 증권 · 카드 · 코인 · 금 · 회사(물건)Logo Tile — 각진 타일, 기관 색 + 첫 글자(그림이 있으면 덮는다)
사진 · 카드 그림 · 규정 그림Image Frame
카테고리 · 기능List 의 타일 — 옅은 색 + 아이콘
그림이 아닌 비율 상자(동영상 · 지도)Aspect Ratio
그림 여러 장Scroll Fog row 가로 줄 + Indicator("1 / 12" · "+9") — Carousel 은 걷었다

모양

Image FrameLogo TileAspect Ratio
비율 · 크기1:1 · 2:1 · 16:9 · 4:3(기본) · 6:7 · 4:5 · 2:3 · 카드 1.58632 · 40(기본) · 48Image Frame 과 같은 여덟, 기본 4:3
모서리폭으로 — 24 이하 4 · 48 이하 6 · 그 위 8 · 화면 폭 0크기 × 0.3 — 10 · 12 · 140
윤곽안쪽 1px stroke-neutral-overlay(v118 — 검정 4.7% · 다크 흰 5%), 그림 위에 늘같다없다
맞춤사진 · 카드 그림 cover, 로고 contain(흰 판 static-white)카드 그림은 옅은 판 위 카드 전체 · 로고는 흰 판 위 contain동영상 cover
불러오는 동안같은 모서리의 Skeleton(면 bg-neutral-weak + 반짝임)첫 글자 먼저 — 그림이 오면 덮는다—
없음 · 실패Content Placeholder(10초가 지나도 안 오면 실패)첫 글자 그대로—

그림 위 요소

네 모서리에 하나씩, 틀 하나에 둘까지, 틀 가장자리에서 6(spacing-x1_5) — 틀의 짧은 변이 80 이상일 때만. 상태 · 분류는 Badge solid, 장수 · 길이는 Indicator(알약 · overlay-dim-dark 검정 65% 두 모드 같게 · static-white 11/15 500 · 좌우 6 · 위아래 2 · 높이 19 — 흰 그림 위 7.00:1). 관심(하트) 버튼 · 콘텐츠 종류 아이콘 · 점 지시자 · 화살표 · 자동 넘김은 두지 않는다.

카드 그림

  • 비율 1.586(ISO 카드) — 목록 56 · 혜택 격자 · 상세 모두 같다. 최대 높이로 비율을 바꾸지 않는다.
  • 세로 그림(원래 폭 < 높이)은 시계 방향으로 90° 돌려 가로 틀을 cover 로 채운다 — 다 받은 뒤 방향을 정한다.
  • 그림이 없으면 아는 카드사는 카드 면(기관 색 한 색 + 회사 · 카드 이름, 폭 96 미만은 회사 첫 글자), 모르는 카드사는 Content Placeholder(카드 아이콘). 광택 띠 · 그라디언트 · 브랜드 파랑 대역은 두지 않는다.
  • 상세는 그림이 떠도 카드 이름을 글로 둔다. 단종은 흐리지 않고 "단종" 배지.

기관 색 — 브랜드 hex 는 표 하나에만

은행 · 증권 · 카드사 · 코인 · 금 기관의 브랜드 색은 디자인 토큰이 아니라 데이터다 — 모드를 따르지 않고(라이트 · 다크 같다), 기관이 늘면 행이 는다. 그래서 머리말 colors 가 아니라 specs/components/institution-colors.yaml(78곳 — 자산 70 + 카드사 8)에 둔다. 브랜드 hex 를 화면 · 컴포넌트 · 제품 코드에 따로 적지 않는다 — 웹 · 앱은 그 표에서 만든 파일(레시피 lib/institution-colors.ts — 앱도 같은 표에서)과 찾기 규칙(기관 이름으로만 — 공백을 뺀 이름 · 별칭이 같으면 그 기관, 아니면 든 가장 긴 이름)만 쓴다. 토큰이 아닌 raw 색은 이 표와 차트 팔레트뿐이다(앱의 "chart palette · bank colors 는 raw palette 예외" 가 가리키는 자리).

  • 같은 회사는 한 색 — 하나 #008485 · NH농협 #00A651(두 표가 달랐다).
  • 글자색은 표의 text — 흰 글자(static-white)가 4.5:1 이상이면 흰색, 아니면 짙은 글자(라이트 fg-neutral · 다크 fg-neutral-inverted). 둘 다 모자라던 중간 밝기 다섯 곳은 명도만 고쳤다(원래 색은 ci). 78곳 모두 4.52:1 이상이다.
  • 표에 없는 기관은 Logo Tile 이 Avatar 의 이름 색(차트 10색 + fg-neutral-inverted)을, 카드 면이 Content Placeholder 를 쓴다.

접근성

  • 이름 옆 그림 · 타일은 장식이다 — 그림 alt="", 타일은 첫 글자까지 숨긴다. 이름을 한 번만 읽는다. 혼자면 이름(그림의 alt · 타일의 role="img" + aria-label)이고, 실패해도 그 이름이 대체 그림 · 첫 글자에 남는다.
  • Indicator 는 보이는 글("+9") 대신 무엇의 수인지 읽는 글("사진 9장 더 있음")을 읽는다.
  • 파일 이름 · "Image" · "logo" 를 이름으로 두지 않는다. 마우스에 그림을 키우지 않는다.

화면 틀 · 이동 — Top Navigation · Bottom Navigation · Side Navigation · Side Panel · Pagination · Floating Action Button

2026-10-04 SEED Top Navigation · Bottom Navigation · Side Navigation · Side Panel · Pagination · Table Pagination · Floating Action Button 구조로 정했다(사용자 결정 — 비교 페이지 https://claude.ai/artifact/B6tsgbw356Kf2Zumvm2v6a, 열하나 + 따라오는 것). 수치 원본은 specs/components/top-navigation.yaml · bottom-navigation.yaml · side-navigation.yaml · side-panel.yaml · pagination.yaml(+ infinite-list.yaml) · table-pagination.yaml · floating-action-button.yaml, 쓰는 규칙은 각 스펙 md 다. 화면 틀(문턱 · 머리 · 화면을 옮길 때 · 랜드마크)과 안전 영역은 Layout 의 "화면 틀" · "Safe Area" 절. 옛 Sidebar · Sheet(옆 패널) · Pagination 절은 다시 정했고, Breadcrumb · Navigation Menu 는 걷었다(SEED 에 없다 — 데스크톱의 위치는 사이드바의 지금 항목이 알린다).

나누기

자리0 – 767768 – 12791280 이상
화면 맨 위Top Navigation 56Top Navigation(Desk 데스크톱 머리 — HR 은 없음)같다
주 메뉴Desk Bottom Navigation · HR ☰ → Side Panel(왼쪽)Side Navigation 접힘 56Side Navigation 펼침 240
긴 목록끝없이 불러오기상황에 따라 — Pagination · 끝없이 불러오기 · 묶음 옮기기(Layout "목록 넘기기")같다
데이터 표Table PaginationTable PaginationTable Pagination
화면의 주 동작탭 바 가운데 + · 탭 바 없는 화면은 Floating Action Button머리의 버튼같다

모양

값
Top Navigation높이 56(위 안전 영역 더함) · bg-layer-default · 선 · 그림자 없음 · 아이콘 버튼 상자 44(= 누르는 영역) · 아이콘 24 · 화면 끝 6 · 버튼끼리 붙음 · 제목 왼쪽 — 탭 첫 화면 text-t8 22 / 30, 그 아래 text-t6 18 / 24, 700 · 글 버튼 44 · 좌우 10 · text-t5 500 · 누름 bg-layer-default-pressed + 2px 축소 · 알림은 점만 · z-sticky
Bottom Navigation떠 있는 알약 66(줄면 48) · 좌우 14(36) · 아래 max(14, 안전 영역 − 6) · 최대 480 · bg-layer-floating(불투명) · shadow-s3 · 안쪽 1px stroke-neutral-subtle · 5칸 · 아이콘 24 · 라벨 text-t1 11 / 15 고정 크기 · 500 · 지금 탭 fg-neutral + 선 2.5 · 다른 탭 fg-neutral-subtle + 선 2 · 가운데 + 원 44 브랜드 채움 · z-sticky
Side Navigation240 · 접힘 56(layout-sidebar · layout-sidebar-collapsed) · 흰 면 bg-layer-default + 오른쪽 1px stroke-neutral-subtle · 머리 64 · 접기 버튼 40 · 18 · 항목 44 · 아이콘 20 · text-t4 500 · 모서리 10(radius-r2_5) · 묶음 이름 text-t4 700 · 지금 항목 bg-neutral-weak-pressed + fg-neutral(굵기 500 그대로 — 2026-10-08) · 접힌 사이드바의 펼침 메뉴는 Menu 표면 · 폭 200 · 줄 44, 1280 미만에서도(Menu Sheet 규칙의 예외 — 2026-10-08)
Side Panel왼쪽(768 미만 주 메뉴 — 화면 폭의 80%) · 오른쪽(1280 이상 — 480 · 720 · 960) · 높이 전체 · 모서리 · 그림자 · 선 없음 · bg-layer-floating · 딤 overlay-dim-light · overlay-dim-dark · 머리 24 / 24 / 16 · 제목 text-t8 · 닫기 상자 52 · 아이콘 22 · 넘칠 수 있는 본문은 Scroll Fog 위 20 · 아래 80 · z-modal
Pagination칸 40 × 40 · 사이 0 · text-t4 700 · 모서리 8 · 지금 쪽 bg-neutral-inverted + fg-neutral-inverted · 이전 · 다음 아이콘만 16 · 9칸(480 이상) · 7칸 · 끝 쪽은 40 빈 칸 · 누르는 영역은 위아래만 44
Table Pagination한 줄 40 · Select medium(최소 96 · 폭과 상관없이 — Select 1280 규칙의 예외, 2026-10-08) "{n}개" + "씩 보기" · 범위 "11-20" + "/ 총 N개"(목록 최대 240) · 이전 · 다음 40 — 끝에서 막힘 · 표 아래 12
Floating Action Button원 56 · 아이콘 24 · 브랜드 채움 · 흰 아이콘 · shadow-s3 · 오른쪽 아래 화면 끝 · 아래 고정 요소에서 20 + 안전 영역 · 화면에 하나 · z-sticky

쓰는 규칙

  • 상단 바 — 높이 56 은 모든 화면이 같다. 스크롤해도 선 · 그림자를 긋지 않는다. 오른쪽 아이콘은 2개 권장 · 3개까지(넘치면 ⋯ + Menu · Menu Sheet), 글 버튼은 하나. ← 는 들어온 화면으로(앞 화면이 없으면 상위 화면)가 기본이고 화면마다 상위 화면(Hierarchy)을 고를 수 있다, ✕ 는 모달 · 독립 흐름만. 투명 바(tone transparent)는 사진이 화면 위를 채우는 상세에서만 — 스크롤하면 바탕이 채워진다(SEED · 2026-10-22 사용자 결정 5C, 막 · 누름 바탕은 열린 일).
  • 하단 탭 바 — 다섯 칸이 어느 화면에서나 같다(더 나누면 화면 위 Tabs). 가운데 + 는 그 화면의 추가 — 이름은 화면마다("거래 추가" · "일정 추가"). 아래로 스크롤하면 48 로 줄되 이름은 남고, 누르면 펴진다. 탭마다 스크롤을 기억하고, 지금 탭을 다시 누르면 맨 위 · 첫 화면.
  • 사이드바 — 1280 이상 펼침 · 768 ~ 1279 접힘, 손으로 접은 것은 기억. 하위가 있는 항목은 펼치기만, 하위가 지금이면 저절로 펼침. 접혔을 때 하위는 아이콘 옆 펼침 메뉴(1280 미만이어도 Menu Sheet 로 바꾸지 않는다 — 2026-10-08), 단독은 이름 말풍선. 긴 이름은 줄을 바꾼다.
  • 옆 패널 — 왼쪽은 768 미만의 주 메뉴(HR 폰 — 이동하면 닫고, 지금 묶음을 펼친 채 연다), 오른쪽은 1280 이상의 보조 작업(1280 미만은 Bottom Sheet). 아래 · 위 패널은 두지 않는다.
  • 목록 넘김 — 상황으로 고른다(Layout "화면 틀" 의 "목록 넘기기", 2026-10-23 사용자 결정). 쪽 단위로 훑는 데스크톱 목록은 Pagination 이 맞을 수 있고(쪽은 주소에 — 칸은 링크), 스크롤로 내려가는 목록(폰 · 긴 목록)은 끝에 닿으면 저절로 더 불러오는 쪽이 자연스럽다(받는 중 · 다시 시도 · 끝 글). 달처럼 자연스러운 묶음이 있는 목록은 묶음 옮기기가 쪽 넘김이다(가계부 거래 — 달 이동). 데이터 표는 Table Pagination. 칸 40 은 누르는 영역 44(v106)의 예외다(위아래만 44 — 사용자 결정 2026-10-04).
  • 떠 있는 버튼 — 탭 바 없는 폰 화면의 주 동작 하나. 글을 붙이거나 스크롤에 접지 않는다.

접근성

  • 머리는 header(main 밖), 주 메뉴는 이름 있는 nav("주 메뉴"), 본문 바로가기 링크. 화면을 옮기면 맨 위 + 초점을 제목(h1)으로, 문서 제목은 "{화면 제목} - 그루 담다".
  • 탭 · 사이드바 항목은 링크 + 지금 화면 aria-current="page"(앱은 selected). 사이드바의 부모 · 접기 버튼은 aria-expanded. 사이드바의 지금 항목은 한 단계 짙은 바탕 · 짙은 글자로만 보인다 — 굵기는 그대로(1.4.1 ⚠, 사용자 결정 2026-10-08).
  • 아이콘만 있는 버튼(상단 바 · + · 떠 있는 버튼)은 이름 필수 — 알림 점은 이름에 넣는다("알림, 새 알림 있음").
  • Pagination — nav "페이지 탐색" · 칸 "N페이지" · 끝 쪽에서 초점을 지금 쪽으로 · 쪽이 바뀌면 알린다. 칸 40 은 AA(2.5.8) ✓ · AAA(2.5.5) ⚠.

입력 — Slider · Toggle · Input OTP · Color Swatch · Icon Picker

2026-10-09 정했다(사용자 결정 — 비교 페이지 https://claude.ai/artifact/CwVJDATSmLtwQoH67wh1zj, 1B · 2C · 3B · 4B · 5A · 6B · 7A · 8A · 9A · 10A · 11B · 12C · 13B · 14B · 15A · 16A · 17A · 18A · 19B · 20A · 21A · 22A + 따라오는 것). SEED 가 컴포넌트로 가진 것은 Slider 와 Toggle Button(코드만)뿐이라, 인증 코드 칸 · 색 고르기 · 아이콘 고르기는 SEED 의 원칙(Text Input 의 "Input을 나누지 말고" · Iconography)에서 groo 가 정했다. 수치 원본은 specs/components/slider.yaml · toggle.yaml · input-otp.yaml · color-swatch.yaml · icon-picker.yaml, 아이콘 세트는 category-icons.yaml, 쓰는 규칙은 각 스펙 md 다. 옛 Slider · Toggle · Input OTP(v69) 절은 다시 정했고 Toggle Group 은 걷었다 — 옛 스펙은 각 .history 의 v-pre-seed-input.*. 토큰은 더하지 않았다.

나누기

고르는 것쓰는 것
범위 안의 자리(임계값 · 비율) · 2 ~ 5단계(별점)Slider
정확한 숫자 · 금액Input — 숫자 키보드 · 뒤 단위
단추 하나가 그 자리에서 켜고 끄는 상태(관심 · 고정 · 비밀값 보기)Toggle — 아이콘 단추. 다른 화면으로 가는 눈(금액 가리기 설정)은 Toggle 이 아니다(2026-10-16)
같은 내용을 2 ~ 4가지로 바로 다르게 보기Segmented Control
2 ~ 4개 짧은 폼 값 · 거르기 · 제안Chip
5개 이상Select
누르는 순간 적용되는 설정 줄Switch
저장해야 적용되는 켜고 끄기 · 할 일 완료Checkbox
메일로 받은 인증 코드Input OTP — Input 한 칸
항목에 붙일 색Color Swatch
카테고리 · 저축 목표의 아이콘Icon Picker — Input Button + 시트 · 팝오버

Toggle Group 은 두지 않는다 — 하나 고르기는 Segmented Control(2 ~ 4) · Chip, 여럿은 Chip, 5개 이상은 Select 다. 글이 있는 켜고 끄기 단추(SEED Toggle Button · 옛 groo Toggle)도 두지 않는다.

모양

값
Slider손잡이 줄 44(줄 전체가 누르는 자리) · 트랙 4 stroke-neutral-weak · 채움 fg-neutral · 손잡이 원 20 bg-neutral-inverted(누르는 동안 24) · 테두리 · 그림자 없음 · 머리 값 16 / 22 · 700 · 말풍선 13 / 18 · 500(끄는 동안 · 호버 · 키보드 포커스) · 아래 양 끝 표식 · 눈금은 2 ~ 5 구간만(트랙을 끊는 틈 4) · 막힘 bg-disabled · fg-disabled
Toggle보이는 40 · 누르는 44 · 아이콘 20 · 바탕은 누름 · 호버에만 · 끔 fg-neutral-muted + 선 2 · 켬 fg-neutral + 선 2.5 · 브랜드 채움 위는 흰 아이콘 · 상단 바 안은 상자 44 · 아이콘 24 · 끔도 fg-neutral(굵기 · 아이콘으로만 가른다)
Input OTPInput 상자형 한 칸 — large 52 · medium 40 · 숫자만 앞 6자리 · 고정폭 숫자 · 아래 설명 줄 · 다시 받기 Button neutralWeak medium(칸 아래 12, 보낸 뒤 60초 막힘)
Color Swatch원 40 · 누르는 44 · 5 × 2(사이 12 · 폭 248) · 차트 10색(라이트 700 · 다크 800-dark) 진한 채움 · 고름 = 2 띄운 2px stroke-neutral-contrast 고리 + 체크 16 fg-neutral-inverted
Icon Picker트리거 Input Button · 1280 미만 Bottom Sheet · 이상 Popover 408 · 찾기 칸 밑줄형 · 묶음 머리 14 · 500 · 칸 48 · 모서리 12 · 아이콘 24 · 고른 칸 안쪽 2px stroke-neutral-contrast + 선 2.5

쓰는 규칙

  • 요청 중에도 막지 않는다 — 누르는 순간 저장되는 Toggle · Switch 와 손을 뗄 때 한 번 저장되는 Slider 는 화면을 바로 바꾸고 요청은 뒤에서 보낸다. 실패하면 되돌리고 그 자리에서 알린다(Slider 는 Field 오류, Toggle 은 Snackbar). 단계마다 저장 · 지연 저장 · 저장 버튼은 두지 않는다.
  • 슬라이더 값 — 지금 값은 Field 머리 오른쪽에 늘, 끄는 동안 말풍선, 아래 양 끝 표식. 단계마다 숫자를 늘어놓지 않는다. 2 ~ 5단계 고르기도 Slider 다(옛 "3개 이하 금지" 는 걷었다).
  • 켜고 끄는 단추 — 이름은 고정하고 켬은 aria-pressed. 아이콘은 지금 상태를 그린다 — 키가 가려져 있으면 eye-off. 다른 화면으로 가는 버튼(순자산 카드의 금액 가리기 눈 → 설정)은 켜고 끄는 단추가 아니라 aria-pressed 를 달지 않는다(2026-10-16). 모으기 단추(관심 · 고정)의 꺼짐은 사선 없이(Iconography). 켬에 바탕을 칠하지 않는다. 상단 바에서는 끔도 이웃 버튼과 같은 진한 색이다(2026-10-09).
  • 인증 코드 — 칸을 나누지 않는다. 붙여넣기 · 자동 채우기에서 숫자만 뽑고(one-time-code · 숫자 키보드), 6자리를 채워도 저절로 보내지 않는다. 설명 줄 "10분 안에 입력해주세요 · 5번 틀리면 다시 받아요." 를 늘 두고, 다시 받기 단추는 남은 초를 붙여 막는다 — 시계로 세지 않는다.
  • 색 — 새 항목은 v110 배정 순서에서 쓰지 않은 첫 색으로 시작한다(늘 빨강이 아니다). 고치기는 고르지 않으면 색을 바꾸지 않고, 팔레트 밖 색 · 색 없는 항목은 격자 앞 "지금 색" · "자동" 칸으로 보인다. 색을 꼭 고르게 하지 않는다.
  • 아이콘 — lucide 전체가 아니라 category-icons.yaml 의 세트(148개 · 13 묶음)만 연다. 한국어 이름 · 찾는 말로 찾고, 0건이면 "'{검색어}'에 대한 아이콘이 없어요". "없음" 은 두지 않는다 — 기본은 태그. 세트 밖으로 저장된 아이콘은 그대로 그린다.

접근성

  • Slider 이름은 Field 라벨, aria-valuetext 에 단위("80%"), 키보드는 APG(포커스한 손잡이의 Home · End, PageUp · PageDown 10단계). 트랙을 눌러도 고른다(끌기 대신).
  • Toggle 은 <button aria-pressed> + 고정 이름(앱 Semantics toggled — 라벨에 상태를 넣지 않는다).
  • Input OTP 는 입력 하나 — Field 라벨 · aria-describedby(설명 · 오류) · 오류 알림. 코드를 보내면 초점을 칸으로.
  • Color Swatch 는 radiogroup(이름 = Field 라벨) · 칸 이름 = 색 이름 · 묶음에 Tab 하나 + 2차원 화살표.
  • Icon Picker 격자는 listbox · 칸 이름 = 한국어 이름 · 격자에 Tab 하나 + 2차원 화살표 · 찾으면 결과 수를 한 번 알린다.
  • 누르는 영역은 44 이상 — 슬라이더 손잡이 줄 44 · 토글 44 · 색 칸 44 · 아이콘 칸 48. 인증 코드 칸 medium 40 은 1280 이상 데스크톱 웹만이다(Input 과 같다).

펼치고 접기 · 나누기 — Accordion · Collapsible · Tree View · Resizable · Scroll Area · Scroll Auto Hide

2026-10-10 정했다(사용자 결정 — 비교 페이지 https://claude.ai/artifact/9uvjeFyjFXc7TaWnpnnQ6H, 1B · 2A · 3A · 4A · 5A · 6A · 7C · 8A · 9A · 10A · 11A · 12B · 13A · 14A · 15A + 따라오는 것, 스펙을 쓰다 나온 16D · 17B). SEED 가 컴포넌트로 가진 것은 Accordion(rootage 3.0.2 · react 2.0.0)과 Breeze 의 Scroll Auto Hide 뿐이라, Collapsible(Accordion 가이드의 한 줄) · 나무 · 나누기 · 스크롤바는 SEED 의 원칙과 groo 의 이웃 결정(List · Card · Side Navigation · Scroll Fog · v104 모션)에서 groo 가 정했다. 수치 원본은 specs/components/accordion.yaml · collapsible.yaml · tree-view.yaml · resizable.yaml · scroll-area.yaml · scroll-auto-hide.yaml, 하위 줄은 list.yaml, 카드 안 아코디언은 card.yaml 이고 쓰는 규칙은 각 스펙 md 다. 옛 Accordion · Collapsible(v70) · Scroll Area · Resizable(v71) · Treeview(v73) 절은 다시 정했다 — 옛 스펙은 각 .history 의 v-pre-seed-collapse.*. 토큰은 더하지 않았다.

나누기

하는 일쓰는 것
상세가 긴 항목 여럿을 묶어 접는다(카드 혜택 · 유의사항)Accordion — 화면 · 카드 안은 inline, 혜택 상세 시트 · 대화상자는 separated
상세 하나를 접고 편다(분할 내역 · 빠르게 맞추기 · 상세 검색 조건)Collapsible — Accordion 항목 하나의 모양
부모 · 하위 두 단계에서 줄은 편집을 열고 하위만 접는다(카테고리)List 하위 줄 — 줄 앞 꺾쇠 단추
여러 단계에서 하나를 골라 옆에 그 내용을 본다(HR 부서)Tree View — APG 트리
목록 · 상세 두 패널의 목록 폭을 바꾼다(HR 관리, 768 이상)Resizable split
대시보드 위젯의 크기를 바꾼다(HR 편집 모드)Resizable widget + ⋮ "크기"
넘친 내용을 스크롤한다Scroll Area — 기본 스크롤 + 전역 스크롤바 한 벌
목록을 넓게 보려고 보조 머리를 스크롤에 숨긴다(폰 원장 머리)Scroll Auto Hide
읽어야 하는 긴 글(규정 · 유의사항 제목 · 부서 이름)자르지 않는다 — 줄을 바꾼다

모양

값
Accordion트리거 위아래 16 · 좌우 24 · 제목 16 / 22 · 500 · 설명 13 / 18 · 500 fg-neutral-subtle · 꺾쇠 20 fg-neutral-subtle · 54(설명이 있으면 74) · 앞 아이콘 22 · 사이 12 · 폰 · 데스크톱 같음 · inline 들인 선 24 stroke-neutral-subtle · separated Card 면(16 · 1px stroke-neutral-weak · 사이 8 · 그림자 없음) · 누름 = List 누름(들임 6 · 모서리 10 · bg-layer-default-pressed · 콘텐츠만 2px) · 펼친 내용 0 / 24 / 16 · text-article-note · fg-neutral-muted · 모두 펼치기는 Card 머리 동작 모양(보이는 32 · 누르는 44) · 포커스 링은 트리거 안쪽
Collapsible트리거는 Accordion 항목 하나(54 · 74) — 흰 면 · 시트의 줄 · 카드 면의 머리(펼친 내용 아래 24) · 경고 상자의 아래 줄(좌우 16 · 위 선 stroke-warning-weak · 누름 bg-warning-weak-pressed)
List 하위 줄줄 앞 꺾쇠 단추 44(모서리 10 · chevron-right 20 · 펼치면 90°) · 줄 앞 4 · 하위 줄은 부모 제목 자리 104 · 하위가 없는 줄도 꺾쇠 자리를 비워 부모 타일이 52 에 선다(17B)
Tree View줄 44 · 위아래 12 · 좌우 8 · 단계마다 20 · 모서리 10 · text-t4 · 꺾쇠 16(칸 20 · 표시만 — 누르는 자리는 줄 전체) · 아이콘 16 · 사이 6 · 고름 bg-neutral-weak-pressed · 누름 bg-layer-default-pressed + 콘텐츠만 2px · 패널 가장자리 8 · 노드 동작 ⋮ 하나(40 · 누르는 44)
Resizable선 1px stroke-neutral-weak(올리기 · 초점 · 끌기에 stroke-neutral-solid) · 손잡이 표시 4 × 24 stroke-neutral-solid · 누르는 폭 16 · 목록 25%(20 ~ 40%) · 위젯 모서리 24 · 표식 9 × 9 2px stroke-neutral-solid · 자리표시 브랜드 옅은 바탕 + 1px 브랜드 점선 · 모서리 16
Scroll Area6px 알약 · 막대 stroke-neutral-solid · 바탕 투명 · Firefox thin + scrollbar-color 는 @supports not selector(::-webkit-scrollbar) 안
Scroll Auto Hide스크롤 상자 맨 위 sticky · 스크롤 거리 1:1 · 끝나면 50% 스냅 motion-duration-d4 motion-ease-enter · translate3d 로만(높이 그대로) · 바탕 bg-layer-default

쓰는 규칙

  • 여럿을 함께 연다 — 아코디언은 늘 여럿을 열고, 목록 머리 오른쪽에 "모두 펼치기"(펼치면 "모두 접기")를 둔다. 항목은 둘 이상이고(하나면 Collapsible) 처음엔 모두 접혀 있다. 상세가 없는 항목은 꺾쇠 없는 그냥 줄이다 — 막힌 트리거 · 꺾쇠만 뒤집히는 줄을 두지 않는다.
  • 줄 전체가 트리거 — Accordion · Collapsible 은 줄 전체를 누르고, 머리 글이 곧 이름이다. 이름은 고정하고 펼침은 aria-expanded 가 알린다. 줄이 따로 하는 일(편집)이 있으면 줄 앞 꺾쇠 단추 44 로 접는다(카테고리 — "{카테고리} 하위 카테고리").
  • 펼쳐도 그 자리에 — 저절로 스크롤하거나 초점을 옮기지 않고, 패널 안에 스크롤 상자를 두지 않는다. 꺾쇠 · 높이는 motion-duration-d6 motion-ease-easing 이고 모션 줄이기면 높이 움직임 없이 150ms 서서히 — 사이드바 하위 펼침 · 나무 · 하위 줄도 같다.
  • 자르지 않는다 — 제목 · 이름 · 규정 글은 줄을 바꿔 다 보인다. "더 보기" · 눌러서 상세로 잘린 글을 펼치지 않는다(Typography v114).
  • 카드 상세 — 혜택 · 유의사항은 웹 · 앱 모두 카드 안 inline 아코디언이고, 혜택 상세 시트 · 대화상자는 separated 다.
  • 원장 머리 — 폰 가계부의 소비 요약과 월 달력은 하나만 펼친다. 원장 머리(월 · 총액 · 주 달력)는 스크롤하면 숨는다 — 상단 바 · Line Tabs 는 숨지 않고 하단 탭 바는 제 규칙으로 줄어든다.
  • 나무 — Tab 하나 · 화살표로 다닌다. 줄 전체가 누르는 자리라 부모 줄을 누르면(Enter · Space 도) 고르면서 펴고 접고, 꺾쇠는 표시만이다(16D — SEED Accordion 의 "터치 영역은 Trigger 전체"). → ← 는 고르지 않고 펴고 접기만 한다. 노드 동작은 나무 밖 ⋮ 하나, 머리말은 두지 않는다.
  • 나누기 — HR 관리의 768 이상에서만, 목록 20 ~ 40%(오른쪽은 60% 아래로 줄지 않는다) · 화면마다 폭을 기억 · 손잡이를 한 번 누르면 25 ↔ 40. 위젯 크기는 모서리를 끌거나 ⋮ "크기" 로.
  • 스크롤 — 기본 스크롤 + 전역 한 벌이고 Radix ScrollArea 는 걷는다. 세로 스크롤바는 숨기지 않는다(가로 줄만 — Scroll Fog).

접근성

  • Accordion · Collapsible 트리거는 heading > button(기본 h3) · aria-expanded · aria-controls, 펼친 내용에 role="region" 을 두지 않는다. 아코디언 트리거 사이 ↓ ↑(돌아가며) · Home · End. 앱은 단추 + 펼침 상태로 읽고, 접힌 내용은 읽지 않는다.
  • Tree View 는 tree · treeitem(aria-level · aria-setsize · aria-posinset · aria-expanded · aria-selected) · group, 나무 전체가 Tab 정지점 하나(roving tabindex). Enter · Space 는 누르기와 같다.
  • Resizable 손잡이는 role="separator" · 이름 "목록 너비" · aria-orientation · 값(지금 · 최소 · 최대 %). 끌지 않는 대안 — 손잡이 한 번 누르기 · 키보드 · 위젯 ⋮ "크기"(WCAG 2.5.7).
  • 안에 초점 가는 것이 없는 스크롤 상자는 tabindex="0" + role="region" + 이름, 시트 · 대화상자 · 팝오버 안 상자는 overscroll-behavior: contain. 숨는 머리는 모션 줄이기면 숨지 않고, 그 안으로 초점이 오면 드러난다.
  • 누르는 영역 — 트리거 줄 54 이상 · 모두 펼치기 · 꺾쇠 단추 · 나무 줄(부모 줄도 줄 전체 — 꺾쇠만 누르는 자리는 없다) · ⋮ 44. 위젯 모서리 24 는 AAA(2.5.5) ✗ — 같은 일을 ⋮ "크기" 로 한다. 나누기 손잡이 16 은 AA(2.5.8)도 ⚠ — 데스크톱 마우스 경계라 사용자가 정했고(12B) 같은 일을 키보드 · 누르기로 한다.

2026-10-15 정했다(사용자 결정 — 비교 페이지 https://claude.ai/artifact/KVyg5Kr95cYUkMT3vsxz1z, 1A · 2A · 3A · 4A · 5A · 6A · 7B · 8A · 9A · 10A + 따라오는 것, 스펙을 쓰다 나온 11D · 12A · 13B · 14A). SEED 가 컴포넌트로 가진 Quantity Picker · Attachment Input(rootage · React)과 조합 예시인 Footer(블록 코드)를 groo 에 처음 둔다 — 디자인 시스템의 마지막 묶음이다. 같은 날 Command(⌘K · cmdk)를 디자인 시스템과 제품에서 걷었다(아래 "Command" 절) — 그 자리였던 HR 역할 고르기는 Select Box 여럿 + "저장"(10A), 프로필 사진은 Avatar + 늘 보이는 버튼(6A)이다. 수치 원본은 specs/components/quantity-picker.yaml · attachment-input.yaml · footer.yaml(사진 바꾸기는 avatar.yaml 의 edit 축), 쓰는 규칙은 각 스펙 md 다. 옛 File Upload(v73) 절은 걷었다 — Attachment Input 이 대신한다. 토큰은 더하지 않았다.

나누기

하는 일쓰는 것
작은 정수를 한 단계씩 — 흔한 값이 열 단계 안쪽(승인 필요 횟수 · 반복 간격 · 부여 시간 · 소요시간)Quantity Picker
흔한 값이 열 단계보다 먼 정수(반복 거래 "총 n회") · 돈 · 소수Input — 숫자 칸
날짜 부분 · 띄엄띄엄 이름 붙은 값(반복 일자 · 할부)Select
여럿 · 사진이 섞이는 첨부(거래 영수증 · 메모 · 휴가 증빙)Attachment Input — 타일
파일 하나를 골라 바로 넘긴다(CSV · Excel 가져오기)Attachment Input — 드롭존(1280 이상 웹) · 파일 선택 버튼(1280 미만 · 앱)
사람의 프로필 사진 한 장을 바꾼다Avatar + "사진 바꾸기" · "사진 지우기"
여럿을 골라 한 번에 반영한다(HR 사용자 역할)Select Box 여럿 + "저장"
사이트 맨 아래 — 탐색 · 정책 · 저작권Footer — 블록 조립

모양

값
Quantity Picker상자 1px stroke-neutral-weak · bg-layer-default · small 36 · medium 40 · large 52(모서리 8 · 8 · 12, 아이콘 16 · 18 · 22, 값 16 / 22 · 16 / 22 · 18 / 24 · 500) · 웹 폼 기본 responsive(1280 미만 52 · 이상 40) · 표 칸 36 · 선 1 × 16 stroke-neutral-subtle · 값 칸 좌우 8 · 가장 긴 값의 폭 · 누름 bg-layer-default-pressed + 그 버튼만 2px · 36 · 40 버튼은 누르는 자리 44 · 끝 fg-disabled(초점은 남는다) · 오류 안쪽 2px stroke-critical-solid · 로딩 원 16 · 18 · 22(Button ghost 의 원과 같은 값)
Attachment Input타일 80 · 모서리 12 · 1px stroke-neutral-weak · 아이콘 24 · 개수 12 / 16("3/10") · 사진 80(윤곽 stroke-neutral-overlay) · 파일 카드 160 × 80(좌우 16 · 썸네일 칸 48 · 이름 12 / 16 · 500 글자 단위 네 줄 · 넘치면 넷째 줄에 확장자 · 크기 11 / 15) · 사이 8 · × 20(4 걸침 · 구멍 24 · 누르는 44) · 올리는 중 원 24 · 실패 "다시 시도" · 대표 띠 24 · 줄은 화면 여백까지 + 끝 흐림 20 · 드롭존 높이 120 · 1px 실선 stroke-neutral-solid(끌기 stroke-neutral-contrast + bg-layer-default-pressed) · 안내 14 / 19 · 500 + "파일 선택" neutralWeak small · 항목을 누르면 메뉴(크게 보기 · 대표로 정하기 · 앞으로 옮기기 · 뒤로 옮기기 | 지우기) · 읽기 전용 · 끄는 사진은 불투명도 0.5(SEED)
Footer틀 1040(layout-max-content) · 위아래 40 · 좌우 32(1280 미만 24) · 영역 사이 40 · 위 선 · 브랜드 20 / 27 · 700 + 소개 13 / 18 · 사이트맵 열 최소 100 · 사이 32 · 열 제목 13 / 18 · 500 fg-neutral-muted · 링크 16 / 22 · 500 사이 16 · 선 stroke-neutral-subtle · 안내 영역 사이 16 · 정책 링크 14 / 19 · 500 fg-neutral-muted 사이 24 · 안내 글 13 / 18 fg-neutral-subtle · 저작권 14 / 19 · 500 · 소셜은 Button ghost large(사이 24)
Avatar 사진 바꾸기108 아래 16 에 "사진 바꾸기"(neutralWeak small) · "사진 지우기"(ghost small · 사진이 있을 때만) · 올리는 중 원 위 딤 + 값 있는 원 24 · 실패는 Field 오류 글
HR 역할 고르기칸 없는 체크 상자(이름 16 · 500 + 역할 설명 13) 여럿 + 아래 "저장"(바뀐 것이 없으면 막힘) — 폰 · 데스크톱 같은 모양

쓰는 규칙

  • 수량 칸은 치지 못한다 — 값 칸은 보기만 하고 한 번에 1 씩이다. 누르고 있어도 반복하지 않고 화살표 키도 없다. 흔한 값이 열 단계보다 먼 자리는 숫자 칸이다. 최소 · 최대는 데이터로 건다(승인 필요 횟수의 최대 = 고를 수 있는 승인자 수). 단위는 값 칸의 글("3회"), 제출은 정수다.
  • 옆 칸과 같은 높이 — 수량 칸은 Input 처럼 웹 responsive · 앱 52, 표 칸은 36. 버튼 줄의 48 에 맞추지 않는다.
  • 첨부는 한 줄 — 항목은 줄을 바꾸지 않고 옆으로 스크롤하며, 사진 · 파일 카드가 파일 종류대로 섞인다. 다 차면 타일이 막힌다. "n/최대" 는 서버의 개수 한도가 있을 때만 그린다.
  • 다시 검사하고 그 자리에서 — accept 를 믿지 않고 형식 · 크기 · 개수를 다시 본다. 거절은 Field 오류 글 한 번("10MB 넘는 파일은 올릴 수 없어요."), 올리기 실패는 항목 덮개 + "다시 시도", 진행은 값 있는 원 24 다(막대를 쓰지 않는다).
  • 드롭존은 1280 이상 웹만 — 끌어 놓기가 없는 폰 · 앱은 "파일 선택" 버튼 + 파일 카드다. 상자 전체를 누르는 자리로 두지 않는다 — 키보드는 버튼으로 닿는다.
  • 흐림은 사진의 두 상태만 — 막힘은 불투명도로 흐리지 않는다(v106). 예외로 사진 항목의 읽기 전용 · 끄는 중은 SEED 그대로 불투명도 0.5 이고, 파일 카드는 글 · 아이콘이 fg-disabled 다(사용자 결정 13B).
  • 누르면 메뉴 — 항목을 누르면 1280 미만 Menu Sheet · 이상 Menu 로 크게 보기 · 대표로 정하기 · 앞으로 옮기기 · 뒤로 옮기기 | 지우기 — 끌지 않고 순서를 바꾸는 길이다(14A). 끝에서는 그 방향이 막히고, × 는 지름길로 남는다.
  • 파일 이름 — 글자 단위로 네 줄까지 보이고(Typography v114 의 예외 — 11D), 넘치면 셋째 줄 끝을 "…" 로 줄이고 넷째 줄에 확장자를 남긴다. 보조 기술에는 전체 이름을 준다.
  • 프로필 사진 — 늘 보이는 버튼으로 바꾸고 지운다. 마우스를 올려야 나타나는 덮개를 두지 않는다.
  • 바닥은 블록 조립 — 순서는 SEED 그대로이고 필수 블록이 없다. 사업자 정보 · 연락처 · 소셜은 값이 생기면 넣는다(지어내지 않는다). 개인정보 처리방침은 로그인 전에도 닿는 바닥에 둔다. 저작권은 "© {해} 그루" 한 벌이다(홈 · SSO 로그인 · HR 문서 · Desk 설명서). groo-home 은 짜임 · 간격 · 글 크기만 따르고 색 · 글꼴은 홈 것을 쓴다 — 안내 글은 4.5 이상으로 짙게 한다.
  • 권한은 저장 한 번 — 역할처럼 권한을 주는 여럿 고르기는 누를 때마다 저장하지 않는다.

접근성

  • Quantity Picker 는 role="group" + 이름(Field 라벨)이다. 버튼 이름은 "줄이기" · "늘리기", 끝은 aria-disabled(초점이 남는다), 값 칸은 aria-live="polite" · aria-atomic, 로딩은 aria-busy.
  • Attachment Input 의 타일 이름은 "{칸 이름} 첨부, 3/10", × 는 "{파일 이름} 지우기", 항목 이름은 전체 파일 이름 + 크기 + 상태다. 포커스 링은 모두 부품 안쪽이다(가로 스크롤 줄이 바깥 링을 자른다). 순서 바꾸기는 끌기 · 항목 메뉴(포인터 한 번 — 2.5.7 ✓) · 키보드(Space · ← → · Space · Esc, 한국어 읽기 글) 셋으로 한다. 드롭존의 키보드 길은 "파일 선택" 버튼이다.
  • Footer 는 <footer>(contentinfo) · 사이트맵 <nav aria-label="사이트 지도"> 이고, 새 탭 링크는 보이지 않는 "(새 탭)" + ↗(장식)이다.
  • 누르는 영역 — 수량 버튼 · × 는 보이지 않는 여백으로 44, 첨부 타일 80, "파일 선택" 은 Button 의 44. 바닥의 글 링크(22 · 19)는 AAA ⚠ — SEED 와 같고, 간격 예외로 AA 는 ✓.

Pagination (v67 추가)

2026-10-04 다시 정했다 — 위 "화면 틀 · 이동" 절과 specs/components/pagination.md · table-pagination.md(SEED Pagination · Table Pagination). 옛 numbered · prev-next · load-more 변형, 지금 쪽 primary 채움, sm 32 · md 40 · lg 48 은 걷었다 — 폰의 긴 목록은 끝없이 불러오기이고 "더 보기" 버튼은 두지 않는다. 옛 스펙은 specs/components/pagination.history/v-pre-seed-nav.*.

Sheet — 옆 패널 (v67 추가)

2026-10-04 다시 정했다 — 옆 패널은 Side Panel(specs/components/side-panel.md — 왼쪽 · 오른쪽만, 평평). 위 "화면 틀 · 이동" 절. 아래에서 올라오는 것은 Bottom Sheet, 위에서 내려오는 패널은 걷었다. 옛 스펙은 specs/components/sheet.history/v-pre-seed-nav.*.

Spinner / Progress (v67 추가)

2026-10-03 걷었다 — 스피너는 Progress Circle, 막대는 미터인 Progress 다(위 "기다림" 절, specs/components/progress-circle.md · progress.md). 옛 스펙은 spinner.history · progress.history 의 v-pre-seed-loading.*.

Stepper (v67 추가 · 기록 — 아직 SEED 와 다시 정하지 않았다)

다단계 form / 결재 흐름 / onboarding 시각화. 새 토큰 0 — primary + semantic + spacing 합성.

Variant

Variant방향사용
horizontal (default)좌→우desktop form (HR 휴가 신청 3단계, Desk 가계부 분류 설정)
vertical위→아래mobile 또는 단계 라벨 길어 horizontal 부적절 시
simple progress점 dot 진행minimal (Desk onboarding 5단계 dot indicator)

State

State시각 (step circle)
completedsuccess 채움 + ✓ icon (text-on-accent)
currentprimary 채움 + 단계 번호 (text-on-accent) + outer ring border-focus 2px
pendingsurface-input 배경 + 단계 번호 (text-tertiary)
errorerror 채움 + ! icon (단계 검증 실패)
disabled (skip 가능 단계)text-disabled + opacity 0.5

Anatomy

  • step circle: 32×32 default, sm 24, lg 40 (touch-min 44 충족 위해 sm은 padding 보강)
  • 라벨: circle 아래 (horizontal) 또는 우측 (vertical), caption (12/400)
  • connector line: step 사이 1px border-default (pending) 또는 2px success (completed)
  • gap: step 사이 lg (16px) horizontal, md (12px) vertical

Layout

  • horizontal: viewport breakpoint-md (768px) 이상에서만 사용. 그 이하는 vertical 자동 전환
  • vertical: 좌측 dot column + 우측 라벨/내용
  • 4단계 이상: 모바일에서 vertical 권장 (horizontal 너무 좁음)

Sequential vs Free navigation

  • sequential (default): 이전 단계 완료 후 다음 단계 진입 가능. 비완료 단계 클릭 비활성
  • free: 모든 단계 자유 이동 (settings 메뉴 등). 단, 의존성 있는 단계는 disabled

Motion

  • 단계 전환: completed↔current 색 트랜지션 motion-duration-base (200ms) motion-ease-out
  • connector line fill (next step 진입 시): width 0 → 100% motion-duration-slow (300ms) motion-ease-out
  • error 단계: 진동 (shake keyframes 200ms) — prefers-reduced-motion: reduce 시 색만 변화

Accessibility

  • <nav aria-label="결재 단계"> wrapper
  • <ol> + <li> (semantic order)
  • current step aria-current="step"
  • completed step aria-label="단계 1: 신청자 정보, 완료", current aria-label="단계 2: 기간 입력, 현재", pending aria-label="단계 3: 사유, 미진행"
  • 키보드: Tab으로 단계 이동 (sequential은 disabled 단계 skip)
  • sequential mode 진입 차단 시 screen reader "이전 단계 완료 후 진입 가능" 안내
  • error 단계: aria-invalid="true" + alert text 동반

HR / Desk 듀얼 브랜드

spec brand-neutral. brand 파일 — HR(결재 단계 horizontal, sequential), Desk(onboarding dot indicator simple, free 옵션).

2026-10-04 걷었다 — SEED 에 없고, 데스크톱의 위치는 사이드바의 지금 항목(부모 자동 펼침)과 본문 제목이 알린다(화면 틀 · 이동 결정 9). 옛 스펙은 specs/components/breadcrumb.history/v-pre-seed-nav.*.

2026-10-04 다시 정했다 — Side Navigation(specs/components/side-navigation.md — 240 · 접힘 56 · 머리 64 · 항목 44). 위 "화면 틀 · 이동" 절. 옛 스펙은 specs/components/sidebar.history/v-pre-seed-nav.*.

2026-10-04 걷었다 — 데스크톱 머리의 메가 메뉴는 두 제품 모두 쓰는 곳이 없다(화면 틀 · 이동 추가 결정). 접힌 사이드바의 하위 펼침 메뉴는 Side Navigation 안에서 Menu 모양으로 정한다. 옛 스펙은 specs/components/navigation-menu.history/v-pre-seed-nav.*.

2026-10-02 걷었다 — 세 제품 모두 쓰는 곳이 없다(메뉴 · 툴팁 결정 6). 옛 스펙은 specs/components/menubar.history/v-pre-seed-menu.*. 줄 · 화면의 동작은 "메뉴 · 메뉴 시트 · 도움말 말풍선 · 툴팁" 절.

Command (Cmd+K menu, v68 추가)

2026-10-15 걷었다 — 세 제품 모두 ⌘K 팔레트를 쓰지 않는다(Desk 웹 팔레트는 2026-09-01 에 지웠다). cmdk 는 고르기 칸 두 곳의 검색 목록으로만 남아 있었다 — Desk 카드 상품 고르기(쓰는 곳 없음)는 지우고, HR 역할 고르기는 Select Box 여럿 고르기(CheckSelectBox — 이름 + 역할 설명) + 아래 "저장" 한 번으로 바꾼다(마무리 10A — 폰 · 데스크톱 같은 모양, 아래 "마무리" 절 · specs/components/select-box.md). 옛 스펙은 specs/components/command.history/v-pre-drop.*. 검색해 고르는 긴 목록은 Input Button + Searchable List.

HR / Desk 듀얼 브랜드 (v68 5종 공통)

spec brand-neutral. 사이드바 · 머리 메뉴는 2026-10-04 "화면 틀 · 이동" 절로 옮겼다(Menubar 는 2026-10-02 걷었다).

Combobox (v69 추가)

2026-10-15 걷었다 — 칸에 바로 치는 콤보박스를 두지 않는다. 짧은 선택지는 Select, 검색해 고르는 긴 목록은 Input Button 이 여는 Searchable List 다(SEED 도 Combobox 를 두지 않는다 — Select 문서). 쓰는 곳 없는 카탈로그 항목만 남아 있었다.

Slider (v69 추가)

2026-10-09 다시 정했다 — 위 "입력" 절과 specs/components/slider.md(SEED Slider). 옛 브랜드 채움 · 흰 손잡이 16 + 브랜드 테두리 · 그림자 · 손잡이 위 · 옆 라벨 · 5 / 10 단위 가는 눈금 · 세로 슬라이더 · 호버 1.1배 · 불투명도 막힘 · PageUp ±10% 는 걷었다. 옛 스펙은 specs/components/slider.history/v-pre-seed-input.*.

Toggle (v69 추가)

2026-10-09 다시 정했다 — 켜고 끄는 아이콘 단추 하나(위 "입력" 절과 specs/components/toggle.md). 글 · 아이콘 + 글 변형, 켬의 바탕 · 테두리, 불투명도 막힘은 걷었다 — 거르기는 Chip, 설정은 Switch 이고 서식 툴바는 쓰는 곳이 없다. 옛 스펙은 specs/components/toggle.history/v-pre-seed-input.*.

Toggle Group (v69 추가)

2026-10-09 걷었다 — 하나 고르기 2 ~ 4칸은 Segmented Control, 여럿 · 짧은 폼 값은 Chip, 5개 이상은 Select 다(위 "입력" 절). 옛 스펙은 specs/components/toggle-group.history/v-pre-seed-input.*.

Input OTP (v69 추가)

2026-10-09 다시 정했다 — Input 한 칸(위 "입력" 절과 specs/components/input-otp.md). 칸마다 입력 · 6칸 · 3-3 구분 · 자동 다음 칸은 걷었다 — 칸을 나누지 않는다(SEED Text Input). 옛 스펙은 specs/components/input-otp.history/v-pre-seed-input.*.

HR / Desk 듀얼 브랜드 (v69 5종 공통)

spec brand-neutral. Slider · Toggle · Input OTP 의 쓰는 자리는 2026-10-09 "입력 — HR" · "입력 — Desk" 절로 옮겼다(Toggle Group 은 걷었다).

Accordion (v70 추가)

2026-10-10 다시 정했다 — 위 "펼치고 접기 · 나누기" 절과 specs/components/accordion.md(SEED Accordion). 옛 single 기본 · 트리거 surface-default 바탕 + 1px 테두리 · 호버 바탕 · 펼침 200ms + 투명도 · 꺾쇠 150ms · 모션 줄이기면 즉시 · 펼친 내용 region 은 걷었다 — 늘 여럿 + 모두 펼치기, 펼침은 300ms · 줄이기면 150ms 서서히. 옛 스펙은 specs/components/accordion.history/v-pre-seed-collapse.*.

Collapsible (v70 추가)

2026-10-10 다시 정했다 — 트리거는 Accordion 항목 하나의 모양(위 "펼치고 접기 · 나누기" 절과 specs/components/collapsible.md). 옛 글 · 아이콘 + 글 트리거 · "자세히" · 긴 코드 접기 쓰임 · 펼친 내용 region 은 걷었다 — 잘린 글은 펼치지 않고 자르지 않는다. 옛 스펙은 specs/components/collapsible.history/v-pre-seed-collapse.md.

Hover Card (v70 추가)

2026-10-02 걷었다 — 쓰는 곳이 없다(메뉴 · 툴팁 결정 6). 옛 스펙은 specs/components/hover-card.history/v-pre-seed-menu.*. 짧은 설명은 Tooltip · Help Bubble, 버튼이 있는 내용은 Popover.

Context Menu (v70 추가)

2026-10-02 걷었다 — 쓰는 곳이 없다(메뉴 · 툴팁 결정 6). 옛 스펙은 specs/components/context-menu.history/v-pre-seed-menu.*. 우클릭 · 길게 누르기로만 열리는 메뉴는 두지 않는다 — 줄의 동작은 줄을 눌러 들어간 화면에(여럿이면 머리 ⋮, 표 줄은 줄 끝 ⋮ — 2026-10-25).

Alert Dialog (v70 추가)

2026-10-02 SEED Alert Dialog 로 다시 정했다 — 위 "시트 · 대화상자 · 확인창 · 팝오버" 절과 specs/components/alert-dialog.md 를 따른다.

Table

2026-10-08 — 원본은 specs/components/table.md · table.yaml(SEED 문서 표 · 디자인 그림). 옛 Table · Data Table(v71)을 합쳤다 — 회색 대문자 머리 · 머리 바탕 · 줄무늬 · compact · 고른 줄 브랜드 8% + 왼쪽 선 · 칸 사이 화살표 이동 · 열 크기 조절 · 열 순서 바꾸기는 걷었다.

자리값
머리 줄41 — 위아래 10 · 좌우 16 · 14 / 20 · 500 · fg-neutral, 바탕 없음
본문 줄45 — 위아래 12 · 좌우 16 · 14 / 20 · 400. 썸네일 · 두 줄 칸이 있으면 72
줄 선1px stroke-neutral-subtle — 마지막 줄까지, 세로 선 · 줄무늬 없음
숫자 열오른쪽 + 고정폭 숫자(머리도), 고정폭 글꼴 없음 · 돈은 원까지 · 빼기 U+2212
정렬머리 칸 전체가 버튼 · ↑↓ 늘 보임(fg-neutral-muted, 지금 방향만 fg-neutral) · aria-sort · 누를 때마다 내림 ↔ 오름 두 단계(숫자 · 날짜 열은 처음 내림)
줄 동작줄 끝 ⋮(보이는 40 · 누르는 44 · "{줄} 더보기", 머리 글 없음) · 줄을 누르면 상세
선택첫 열 Checkbox 24 · 고른 줄은 바탕 없이 체크로만 · 고른 줄이 있으면 표 위 일괄 작업 바(브랜드 파일의 brand-weak 역할 색 한 값 · 48 · 모서리 12). 바 안 동작은 모두 ghost neutral — 지우기의 빨강은 확인창에서(2026-10-17 01T-033 A)
768 미만List 줄 — 첫 열은 제목, 다음 열 1 ~ 2개는 설명, 핵심 숫자 · 상태는 오른쪽 값, 나머지는 상세. 넘김은 끝없이 불러오기
빈 · 실패 · 로딩머리는 그리고 본문 자리에 줄 스켈레톤 · Result Section medium(실패는 다시 시도)
의미<table> · <caption> · <th scope> · aria-sort — 표처럼 보이는 div 격자를 두지 않는다
넘김표 아래 Table Pagination — 표 아래 12 는 넘김 줄이 갖고, 표의 넘김 줄 자리는 좌우 24 만(2026-10-17 03-D 결정 5 B)

Data Table (v71 추가)

2026-10-08 걷었다 — 위 Table 절과 specs/components/table.md 로 합쳤다(정렬 · 선택 · 일괄 작업 · 머리 고정 · 넘김). 열 거르기 · 표 위 검색 · 열 보이기 바꾸기 · 내보내기 줄은 이번에 정하지 않았다.

2026-10-04 걷었다 — 세 제품에 쓰는 곳이 0이고 SEED 에도 캐러셀 컴포넌트가 없다(사용자 결정 — 이미지 비교 7A). 그림 여러 장은 끝이 보이는 가로 줄(Scroll Fog row)에 Image Frame 을 잇고, 장수는 Indicator 글("1 / 12" · "+9")로 알린다 — "이미지 — Image Frame · Aspect Ratio · Logo Tile" 절. 점 지시자 · 화살표 · 자동 넘김은 두지 않는다. 옛 스펙은 specs/components/carousel.history/v-pre-seed-image.*.

Scroll Area (v71 추가)

2026-10-10 다시 정했다 — 기본 스크롤 + 전역 스크롤바 한 벌(위 "펼치고 접기 · 나누기" 절과 specs/components/scroll-area.md). 옛 always-visible · hover · scrolling 변형 · 6 ~ 8px · surface-input 바탕 · 불투명도 0.4 ~ 1 · "필요 시 이름" 은 걷었다 — 6px 알약 · Firefox 두 줄은 @supports not selector(::-webkit-scrollbar) 안 · 초점 가는 것이 없는 상자는 tabindex="0" + 이름. 옛 스펙은 specs/components/scroll-area.history/v-pre-seed-collapse.*.

Resizable (v71 추가)

2026-10-10 다시 정했다 — HR 관리 화면 나누기 · 대시보드 위젯 크기(위 "펼치고 접기 · 나누기" 절과 specs/components/resizable.md). 옛 손잡이 4 ~ 6px · hover 브랜드 색 · 세로 · 중첩 · snap 25 / 50 / 75% · ±1% · Enter · Space 로 접기 · "localStorage 권장" 은 걷었다 — 선 1px + 손잡이 표시 · 누르는 폭 16 · 5% · 목록 20 ~ 40% · 화면마다 기억 · 한 번 누르면 25 ↔ 40. 옛 스펙은 specs/components/resizable.history/v-pre-seed-collapse.*.

HR / Desk 듀얼 브랜드 (v71 5종 공통)

spec brand-neutral. Scroll Area · Resizable 의 쓰는 자리는 2026-10-10 "펼치고 접기 · 나누기 — HR" · "— Desk" 절로 옮겼다. Table · Data Table 은 2026-10-08 Table 절로 합쳤고, Carousel 은 2026-10-04 걷었다.

Sonner (v72 추가, Toast 강화)

2026-10-02 걷었다 — Snackbar 로 바꿨다("알림 메시지 — Snackbar · Callout · Page Banner · Result Section" 절). 옛 스펙은 specs/components/sonner.history/v-pre-seed-feedback.*.

Aspect Ratio (v72 추가)

2026-10-04 SEED Aspect Ratio 로 다시 정했다 — "이미지 — Image Frame · Aspect Ratio · Logo Tile" 절과 specs/components/aspect-ratio.md. 그림이 아닌 자리(동영상 · 지도)의 비율 상자이고, 비율은 Image Frame 과 같은 여덟 가지다(기본 4:3 — 옛 16:9 기본 · 3:2 · 21:9 · 9:16 을 걷었다). 그림은 Image Frame 이다. 옛 스펙은 specs/components/aspect-ratio.history/v-pre-seed-image.*.

Chart

2026-10-08 — 원본은 specs/components/chart.md · chart.yaml. 색은 Colors 의 v110 · v111 이다. 옛 v72 의 아래 범례 · hover card 툴팁 · 16:9 · 데이터 점마다 tabindex 는 걷었다.

자리값
색차트 10색 — 라이트 700 · 다크 800-dark. 저장된 색 먼저, 색이 없는 항목은 그 차트에서 아직 쓰지 않은 색부터 배정 순서로. 회색은 "기타" 전용
눈금 글자11 / 15(text-t1) · fg-neutral-subtle · 고정폭 숫자 — 이중 축이면 그 계열의 색. 돈 축만 "만" 으로 줄인다
격자가로 점선(3 · 3) stroke-neutral-subtle 만 — 세로 격자 · 축 선 없음
이중 축크기가 열 배 넘게 다른 두 계열(수입 · 지출) — 왼쪽 · 오른쪽 눈금
툴팁떠 있는 표면 bg-layer-floating · shadow-s3 · 모서리 12 — 머리 12 · fg-neutral-subtle, 줄 "■ 라벨 값"(값 700 · 원까지)
선 · 막대 범례차트 위 지표 타일(점 + 이름 + 합계, 켠 계열 바탕 chart-{색}-subtle) — 누르면 계열을 켜고 끈다
도넛 범례카테고리 목록(색 네모 + 이름 + % + 금액 "원") · 가운데 합계도 원까지
열지도칸 정사각형 · 모서리 4 · 사이 6, 세기 다섯(브랜드 채움 18 ~ 100%) — 칸 폭 112 이상에서만 금액을 원까지(11 · 700), 좁으면 세기 색만 · 값은 툴팁 · 표로 보기
가로축오늘에서 끝난다 — 오늘 뒤 날짜를 0 으로 그리지 않는다
빈 · 실패 · 로딩차트 자리 Skeleton(모서리 16) · Result Section medium(실패는 다시 시도)
보조 기술차트 상자 role="img" + 요약 이름 · 범례 목록이 대체 · "표로 보기" · 모션 줄이기면 바로 그린다

Date Range Picker (v72 추가)

2026-10-03 걷었다 — 기간은 Date Picker 기간("날짜 · 시각 고르기" 절)이다. 칸 하나 · 달력 하나, 빠른 기간은 한 벌(옛 "오늘 / 어제 / 지난 7일 …" + "취소 · 적용" 을 대신).

Time Picker (v72 추가)

2026-10-03 걷었다 — 시각은 Time Picker("날짜 · 시각 고르기" 절 · specs/components/time-picker.md)다. 치는 칸 · 24시간("14:30")을 오전·오후 12시간 휠로 바꿨다.

HR / Desk 듀얼 브랜드 (v72 5종 공통)

spec brand-neutral. brand 파일 — HR(Sonner top-right 결재 알림 stack / Chart bar/line dashboard / Date Range Picker dual desktop / Time Picker 결재 일정 5분 step), Desk(Sonner bottom-center 모바일 / Chart pie 가계부 카테고리 / Aspect Ratio 16:9 메모 attachment / Date Range Picker single 모바일).

2026-10-02 걷었다 — 화면 안 안내는 Callout, 페이지 맨 위 띠는 Page Banner 다("알림 메시지 — Snackbar · Callout · Page Banner · Result Section" 절).

Chip

수치 · 규칙의 원본은 specs/components/chip.md · chip.yaml 이다 — 2026-10-02 SEED Chip 구조로 새로 정했다(옛 v73 Tag / Chip 을 대신한다). 고르거나 넣은 값을 보이는 작은 알약이고, 누를 수 없는 표시(상태 · 분류 · 메타)는 Badge · Tag Group 이다(위 "Badge · Notification Badge · Tag Group" 절). 이 절은 토큰과 닿는 자리만 모은다.

쓰임

쓰임의미고른 모습
고르기 — 하나(2 ~ 4개 짧은 폼 값 · 거르기의 한 축)라디오 — 다시 눌러도 풀리지 않는다, "전체" 는 맨 앞 선택지있다
고르기 — 여럿체크박스 — 다시 누르면 풀린다, "전체 선택" 칩은 두지 않는다있다
제안(빠른 금액 · 빠른 기간 · 프리셋)버튼 — 누르면 칸에 값을 넣는다없다
필터 바(목록 위, 조건마다 칩 · 뒤 아래 화살표)버튼 — 그 조건만 시트 · 팝오버로 연다걸린 조건은 짙은 채움 + 값 요약("식비 외 2개")
입력값글 + "{글} 지우기" 버튼Outline Weak 고른 모습

모양과 색

요소값
크기small 32 · medium 36(기본) · large 40, 모서리 radius-full, 글 t4 14 · 500(세 크기 같다), 좌우 12 · 14 · 16, 앞 아이콘 14 · 16 · 16 과 글 사이 6
Solid안 고름 bg-neutral-weak-alpha(투명 — 회색 바닥 · 흰 표면 어디서나, v120) · 고름 bg-neutral-inverted + fg-neutral-inverted
Outline Strong안 고름 투명 + 안쪽 1px stroke-neutral-weak · 고름 bg-neutral-inverted(테두리 없음)
Outline Weak(기본)안 고름 투명 + 1px stroke-neutral-weak · 고름 bg-neutral-weak + 1px stroke-neutral-contrast(글자 그대로)
누름 · 호버bg-neutral-weak-pressed · bg-layer-default-pressed · bg-neutral-inverted-pressed, 칩 전체 2px 거리 축소(v104)
비활성bg-disabled · fg-disabled(흐림 없음 — v106). 고른 채 막히면 1px stroke-neutral-solid 를 남긴다
묶음칩 사이 spacing-between-chips(8). 폼 · 시트 안은 줄바꿈(줄 사이 8), 목록 위 줄은 가로 스크롤(안쪽 여백 spacing-global-gutter)

고른 칩은 브랜드 색이 아니라 중립색이다 — Desk · HR 이 같고, 고른 칩이 여럿 보여도 브랜드 버튼과 다투지 않는다(사용자 결정 2026-10-02).

쓰는 규칙

  • 2 ~ 4개 짧은 폼 값은 Chip, 5개 이상은 Select, 글이 긴 2 ~ 4개는 Radio · Checkbox.
  • 3상태 칩(고름 → 빼고 → 해제)은 두지 않는다 — 빼는 조건은 "고른 것만 · 고른 것 빼고" 를 먼저 고른다.
  • 제안 칩은 고른 모습으로 남기지 않는다. 필터 바는 걸린 조건 칩의 글이 곧 조건이라 "필터 2" 같은 개수를 따로 두지 않는다.
  • 칩 모양 탭(Tabs 의 Chip Tabs)과 필터 칩을 한 화면에 같은 모양으로 두지 않는다 — 탭을 Line 으로.

Accessibility 체크리스트

  • 하나 고르기 radiogroup(화살표로 옮기면 고른다) · 여럿 체크박스 · 제안 · 여는 칩은 버튼(여는 칩 aria-haspopup="dialog") — aria-pressed 는 쓰지 않는다
  • 묶음 이름은 Field 라벨 · aria-label, 아이콘만 있는 칩은 aria-label
  • 키보드 포커스에만 링 2px · 띄움 2px, 누르는 영역은 가로 · 세로 44 까지(아이콘만 있는 칩도)
  • 입력값 지우기 이름 "{글} 지우기", 지운 뒤 포커스는 다음 칩

Popover (v73 추가)

2026-10-02 SEED Popover 로 다시 정했다 — 위 "시트 · 대화상자 · 확인창 · 팝오버" 절과 specs/components/popover.md 를 따른다.

File Upload (v73 추가)

2026-10-15 걷었다 — 사진 · 파일을 붙이는 칸은 Attachment Input(specs/components/attachment-input.md — SEED, 위 "마무리" 절)이다. 옛 2px 점선 상자 · 회색 바탕 · 📁 · 끌기 때 브랜드 테두리 + 8% 바탕 · 막힘 불투명도 0.5 · 성공 ✓ 글은 걷었다 — 드롭존은 1px 실선 stroke-neutral-solid(끌기 stroke-neutral-contrast + bg-layer-default-pressed)이고, 올리는 중은 값 있는 원 24, 실패는 "다시 시도" 다.

Treeview (v73 추가)

2026-10-10 다시 정했다 — 여러 단계에서 고르는 나무는 Tree View(APG Treeview — specs/components/tree-view.md, HR 부서), 하위 줄을 접는 카테고리는 List 하위 줄(specs/components/list.md)이다(위 "펼치고 접기 · 나누기" 절). 옛 고름 surface-input + 왼쪽 브랜드 2px · 여럿 고르기 · 끌어서 옮기기 · 안내 선 · 메모 폴더 나무는 걷었다.

HR / Desk 듀얼 브랜드 (v73 5종 공통)

spec brand-neutral. brand 파일 — HR(Banner 약관 변경 / Chip 결재라인 입력값 칩 / Popover 결재 의견 입력), Desk(Banner 시스템 점검 / Chip 메모 태그 입력값 칩 / Popover 카테고리 quick edit). 나무의 쓰는 자리는 2026-10-10 "펼치고 접기 · 나누기 — HR" · "— Desk" 절로, 첨부의 쓰는 자리는 2026-10-15 "마무리 — HR" · "— Desk" 절로 옮겼다.

이 페이지

Button변형과 색상태크기누르는 영역 · 배치Accessibility 체크리스트Input · Textarea모양과 색크기쓰는 규칙Accessibility 체크리스트Select · Input Button나누기트리거 · 칸목록(Select)쓰는 규칙Accessibility 체크리스트CardPage textCaptionBadge · Notification Badge · Tag Group나누기모양쓰는 규칙접근성Alert textFocus ringMode pair (sparse — brand 토큰이 contrast 검증 담당)SpecWCAG 검증사용 예시 (CSS 의사코드)LayoutMotionAccessibility 체크리스트DividerOutline (border 시각 요소 · 기록 — 기준은 Dialog · Popover 스펙과 v104 의 선)Mode pairSpec사용 시나리오Contrast (UI 1.4.11)AccessibilityDisabled label (기록 — 기준은 v106 상태 — 막힌 글자 fg-disabled · 바탕 bg-disabled, 불투명도를 쓰지 않는다)Mode pair (sparse — textColor만 정의, backgroundColor 없음)의도SpecLayoutAccessibilityChart color (palette)Mode pair (10색 × 2 = 20 토큰)Hue 정렬 의도L 통일의 의도VariantLayoutMotionAccessibility사용 예시 (CSS 의사코드)시트 · 대화상자 · 확인창 · 팝오버나누기 — 떠 있는 표면 일곱, 상황 → 고를 것모양쓰는 규칙Accessibility 체크리스트알림 메시지 — Snackbar · Callout · Page Banner · Result Section나누기모양쓰는 규칙접근성메뉴 · 메뉴 시트 · 도움말 말풍선 · 툴팁나누기모양쓰는 규칙접근성Tabs · Segmented Control나누기LineChip TabsSegmented Control쓰는 규칙Accessibility 체크리스트Switch / Checkbox / Radio (control 묶음)의미 차이Spec 공통 (신규 토큰 없음)SwitchCheckboxRadioLayoutTouch target (WCAG 2.5.5)AccessibilityListSelect BoxAvatar · Avatar Stack날짜 · 시각 고르기 — Date Picker · Time Picker · Wheel PickerField (폼 — 라벨 · 설명 · 오류)짜임규칙검증과 나가기오류 글 꼴(v75 에서 옮겨 Writing 에 맞췄다)기다림 — Skeleton · Progress Circle · Progress · Content Placeholder · Scroll Fog나누기시간표 — 1초 · 5초 · 10초모양쓰는 규칙접근성이미지 — Image Frame · Aspect Ratio · Logo Tile나누기모양그림 위 요소카드 그림기관 색 — 브랜드 hex 는 표 하나에만접근성화면 틀 · 이동 — Top Navigation · Bottom Navigation · Side Navigation · Side Panel · Pagination · Floating Action Button나누기모양쓰는 규칙접근성입력 — Slider · Toggle · Input OTP · Color Swatch · Icon Picker나누기모양쓰는 규칙접근성펼치고 접기 · 나누기 — Accordion · Collapsible · Tree View · Resizable · Scroll Area · Scroll Auto Hide나누기모양쓰는 규칙접근성마무리 — Quantity Picker · Attachment Input · Footer나누기모양쓰는 규칙접근성Pagination (v67 추가)Sheet — 옆 패널 (v67 추가)Spinner / Progress (v67 추가)Stepper (v67 추가 · 기록 — 아직 SEED 와 다시 정하지 않았다)VariantStateAnatomyLayoutSequential vs Free navigationMotionAccessibilityHR / Desk 듀얼 브랜드Breadcrumb (v68 추가)Sidebar (v68 추가)Navigation Menu (v68 추가)Menubar (v68 추가)Command (Cmd+K menu, v68 추가)HR / Desk 듀얼 브랜드 (v68 5종 공통)Combobox (v69 추가)Slider (v69 추가)Toggle (v69 추가)Toggle Group (v69 추가)Input OTP (v69 추가)HR / Desk 듀얼 브랜드 (v69 5종 공통)Accordion (v70 추가)Collapsible (v70 추가)Hover Card (v70 추가)Context Menu (v70 추가)Alert Dialog (v70 추가)TableData Table (v71 추가)Carousel (v71 추가)Scroll Area (v71 추가)Resizable (v71 추가)HR / Desk 듀얼 브랜드 (v71 5종 공통)Sonner (v72 추가, Toast 강화)Aspect Ratio (v72 추가)ChartDate Range Picker (v72 추가)Time Picker (v72 추가)HR / Desk 듀얼 브랜드 (v72 5종 공통)Banner (v73 추가)Chip쓰임모양과 색쓰는 규칙Accessibility 체크리스트Popover (v73 추가)File Upload (v73 추가)Treeview (v73 추가)HR / Desk 듀얼 브랜드 (v73 5종 공통)