Chip
고르거나 넣은 값을 보이는 작은 알약. 2 ~ 4개 짧은 폼 값 고르기 · 누르면 값을 채워 주는 제안 · 목록 위 필터 바 · 넣은 값(지우기 버튼으로 뺀다)을 맡는다. 5개 이상은 Select, 글이 긴 2 ~ 4개는 Radio · Checkbox, 다른 구역으로 옮기는 탭 · 같은 내용을 바로 거르는 2 ~ 4개는 Tabs · Segmented Control(그 차례에), 누를 수 없는 표시는 Badge · Tag Group 이다.
구조는 당근 SEED Chip(Apache-2.0)을 따른다 — 알약(Container) · 글(Label) · 앞 아이콘 · 뒤 아이콘. 하나 고르기는 라디오(Chip.RadioItem), 여럿 고르기는 체크박스(Chip.Toggle), 제안 · 여는 칩은 버튼(Chip.Button)이다. 값은 groo 토큰이고, SEED 와 다른 자리는 맨 아래 "SEED 와 다른 점" 에 적었다(2026-10-01 · 02 사용자 결정).
수치 원본은 chip.yaml이다. 수치 표 자리([표: …])와 그림 자리([그림: …])는 사이트가 그 파일로 그린다 — GitHub 에서는 그 파일 · 그림 코드로 가는 링크로 보인다.
직접 골라 보기
변형 · 크기 · 고르기 방식 · 아이콘 · 상태를 고르면 스펙대로 그린 칩 묶음과 그 코드가 바뀐다. 실제로 누를 수 있다.
import { Field } from "@/components/ui/field"
import { ChipRadio, ChipRadioGroup } from "@/components/ui/chip"
<Field label="거래 종류">
<ChipRadioGroup value={type} onValueChange={setType}>
<ChipRadio variant="outlineStrong" value="expense">지출</ChipRadio>
<ChipRadio variant="outlineStrong" value="income">수입</ChipRadio>
<ChipRadio variant="outlineStrong" value="transfer">이체</ChipRadio>
</ChipRadioGroup>
</Field>Anatomy
| 부위 | 설명 |
|---|---|
| ⓐ Container | 알약 — 모서리 full. 글만큼 넓어지고 줄바꿈하지 않는다. 줄보다 길면 줄 폭에서 멈추고 글 끝을 말줄임한다. |
| ⓑ Prefix Icon | 앞 아이콘 — 묶음 안에서 모두 두거나 모두 뺀다. 없어도 된다. |
| ⓒ Label | 글 — 명사로 짧게, 한 줄. 칩이 줄 폭에 닿을 때만 끝을 "…" 로 줄인다. |
| ⓓ Suffix Icon | 뒤 아이콘 — 누르면 고르는 자리를 여는 칩의 아래 화살표(필터 바). |
| ⓔ Remove Button | 입력값 칩의 지우기 — 칩 안에서 따로 눌린다. |
부위
| 부위 | 설명 |
|---|---|
root | 알약 — 모서리 full. 글만큼 넓어지고 줄바꿈하지 않는다. 줄보다 길면 줄 폭에서 멈추고 글 끝을 말줄임한다(2026-10-17) |
label | 글 — 명사로 짧게, 한 줄. 칩이 줄 폭에 닿을 때만 끝을 "…" 로 |
prefixIcon | 앞 아이콘 — 묶음 안에서 모두 두거나 모두 뺀다 |
suffixIcon | 뒤 아이콘 — 여는 칩의 아래 화살표 |
removeButton | 입력값 칩의 지우기 — 이름 "{글} 지우기", 칩 안에서 따로 눌린다 |
icon | 아이콘만 있는 칩의 아이콘 — 이름(aria-label) 필수 |
focusRing | 키보드 포커스 링(웹) |
group | 묶음(Chip Group) — 줄바꿈(폼 · 시트 안) 또는 한 줄 가로 스크롤(목록 위 필터 바 · 제안 줄) |
scrollRow | 가로 스크롤 줄 — 목록 위 필터 바 · 제안 줄만(줄바꿈 묶음에는 없다). 줄을 화면 끝까지 낸다 |
Properties
Variant
세 가지다. 안 고른 Outline Strong 과 Outline Weak 는 똑같고, 고르면 갈린다.
| 변형 | 안 고름 | 고름 | 쓰는 자리 |
|---|---|---|---|
solid | 옅은 투명 채움(bg-neutral-weak-alpha) | 짙은 채움(bg-neutral-inverted · fg-neutral-inverted) | 제안 · 필터 바 — 회색 바닥 · 흰 표면 어디서나 |
outlineStrong | 투명 + 안쪽 1px stroke-neutral-weak | 짙은 채움(테두리 없음) | 하나 고르기를 분명하게 — 거래 종류처럼 고른 값이 곧 화면의 갈래일 때. 필터 바 맨 앞 지우기(↺, 고르지 않는 칩)도 이 모양 — Solid 조건 칩과 갈린다 |
outlineWeak (기본) | 투명 + 안쪽 1px stroke-neutral-weak | 옅은 바탕 bg-neutral-weak + 짙은 1px stroke-neutral-contrast(글자 그대로) | 고르기의 기본 — 고른 칩이 여럿 보일 때(여럿 고르기 · 시트 안 고르기 · 입력값) |
고른 칩은 브랜드 색이 아니라 중립색으로 칠한다 — 고른 칩이 여럿 보여도 브랜드 버튼(주요 동작)과 다투지 않고, Desk · HR 이 같다. Solid 의 옅은 바탕은 투명한 bg-neutral-weak-alpha(검정 4.7% · 다크 흰 12.5%)라 놓인 바탕에 섞여 회색 바닥(bg-layer-basement) 위에서도 보인다 — 회색 위 1.11:1 · 흰 위 1.11:1 · 다크 1.47:1(v120, 2026-10-16 사용자 결정 — 기초 웹 01-040 B). 불투명 bg-neutral-weak 였을 때는 회색 바닥과 같은 색(1.00:1)이라 흰 표면 위에서만 썼다.
변형 · 고름 · 크기 × 모양 — 바뀌는 값
| 조합 | 상태 | 속성 | 값 |
|---|---|---|---|
size=small + layout=withText | enabled | 최소 너비 | 44px |
size=medium + layout=withText | enabled | 최소 너비 | 48px |
size=large + layout=withText | enabled | 최소 너비 | 52px |
size=small + layout=iconOnly | enabled | 너비 | 32px |
size=small + layout=iconOnly | enabled | 좌우 여백 | 0px |
size=medium + layout=iconOnly | enabled | 너비 | 36px |
size=medium + layout=iconOnly | enabled | 좌우 여백 | 0px |
size=large + layout=iconOnly | enabled | 너비 | 40px |
size=large + layout=iconOnly | enabled | 좌우 여백 | 0px |
variant=solid + selected=unselected | enabled | 배경 | color-bg-neutral-weak-alpha #0000000C · 다크 #FFFFFF20 — SEED 그대로 투명(검정 4.7% · 다크 흰 12.5%) — 놓인 바탕에 섞여 회색 바닥 위 1.11 · 흰 위 1.11 · 다크 1.47:1(v120) |
variant=solid + selected=unselected | enabled | 글자·아이콘 | color-fg-neutral #1A1F2E · 다크 #F5F6FA |
variant=solid + selected=unselected | hovered | 배경 | color-bg-neutral-weak-alpha-pressed #00000010 · 다크 #FFFFFF2E |
variant=solid + selected=unselected | pressed | 배경 | color-bg-neutral-weak-alpha-pressed #00000010 · 다크 #FFFFFF2E |
variant=solid + selected=unselected | disabled | 배경 | color-bg-neutral-weak-alpha #0000000C · 다크 #FFFFFF20 — 막혀도 바탕은 그대로 — 글 · 아이콘만 fg-disabled(공통). bg-disabled(gray-200)는 회색 바닥(bg-layer-basement, 같은 gray-200)과 1.00:1 이라 알약이 사라진다. 투명 바탕은 회색 바닥 위 1.11 · 흰 위 1.11 · 다크 1.47:1. 안 고른 칩과는 글 색으로 갈린다(SEED 도 바탕을 바꾸지 않는다 — 2026-10-17 사용자 결정 03-B 결정 1 A) |
variant=solid + selected=selected | enabled | 배경 | color-bg-neutral-inverted #1A1F2E · 다크 #F5F6FA |
variant=solid + selected=selected | enabled | 글자·아이콘 | color-fg-neutral-inverted #FFFFFF · 다크 #242938 |
variant=solid + selected=selected | hovered | 배경 | color-bg-neutral-inverted-pressed #535866 · 다크 #B7BDCC |
variant=solid + selected=selected | pressed | 배경 | color-bg-neutral-inverted-pressed #535866 · 다크 #B7BDCC |
variant=solid + selected=selected | disabled | 테두리 | color-stroke-neutral-solid #767C8B · 다크 #838997 — 고른 채 막힘 — 회색 채움에 짙은 1px 를 남겨 안 고른 칩과 가른다 |
variant=solid + selected=selected | disabled | 테두리 두께 | 1px |
variant=outlineStrong + selected=selected | enabled | 배경 | color-bg-neutral-inverted #1A1F2E · 다크 #F5F6FA |
variant=outlineStrong + selected=selected | enabled | 테두리 두께 | 0px — 짙은 채움 위 테두리는 지운다(SEED Chip Tabs 와 같다) |
variant=outlineStrong + selected=selected | enabled | 글자·아이콘 | color-fg-neutral-inverted #FFFFFF · 다크 #242938 |
variant=outlineStrong + selected=selected | hovered | 배경 | color-bg-neutral-inverted-pressed #535866 · 다크 #B7BDCC |
variant=outlineStrong + selected=selected | pressed | 배경 | color-bg-neutral-inverted-pressed #535866 · 다크 #B7BDCC |
variant=outlineStrong + selected=selected | disabled | 배경 | color-bg-disabled #F5F6FA · 다크 #353B4D |
variant=outlineStrong + selected=selected | disabled | 테두리 | color-stroke-neutral-solid #767C8B · 다크 #838997 — 고른 채 막힘 — 짙은 1px 로 안 고른 칩과 가른다 |
variant=outlineStrong + selected=selected | disabled | 테두리 두께 | 1px |
variant=outlineWeak + selected=selected | enabled | 배경 | color-bg-neutral-weak #F5F6FA · 다크 #353B4D |
variant=outlineWeak + selected=selected | enabled | 테두리 | color-stroke-neutral-contrast #1A1F2E · 다크 #F5F6FA — 고름 — 짙은 1px(v113) |
variant=outlineWeak + selected=selected | hovered | 배경 | color-bg-neutral-weak-pressed #EDEFF3 · 다크 #404757 |
variant=outlineWeak + selected=selected | pressed | 배경 | color-bg-neutral-weak-pressed #EDEFF3 · 다크 #404757 |
variant=outlineWeak + selected=selected | disabled | 배경 | color-bg-disabled #F5F6FA · 다크 #353B4D |
variant=outlineWeak + selected=selected | disabled | 테두리 | color-stroke-neutral-solid #767C8B · 다크 #838997 — 고른 채 막힘 — 짙은 1px 를 회색으로 남긴다 |
Size
small 32 · medium 36 (기본) · large 40. 글은 세 크기 모두 14 · 500(t4)이고, 글과 가장자리 사이는 12 · 14 · 16, 앞 아이콘 14 · 16 · 16 과 글 사이 6, 칩 사이 8(spacing-between-chips)이다. 기본은 폰 폼에서도 36 이고, small 은 촘촘한 줄(1280 이상 데스크톱의 필터 · 표 위), large 는 화면의 주인공 고르기에만 쓴다. 누르는 영역은 Button 처럼 가로 · 세로 44 까지 넓힌다(보이는 칩은 그대로 — 글이 있는 칩은 최소 폭이 이미 44 이상이고, 아이콘만 있는 칩은 가로도 44).
분홍 띠 — 누르는 영역(가로 · 세로 44 까지 — 글이 있는 칩은 최소 폭이 이미 넘는다, 보이는 칩은 그대로) · 글은 세 크기 모두 14 · 500 · 아이콘과 글 사이 6
크기
| size | 높이 | 좌우 여백 | 앞 아이콘 | 뒤 아이콘 | 지우기 버튼 | 아이콘 | 터치 (AA · AAA) | 설명 |
|---|---|---|---|---|---|---|---|---|
small | 32px — 웹 rem — 큰 글자에서 배율대로. 앱은 최소 높이 — 글을 따라 늘어난다(label 비고) | spacing-x3 12px — SEED 루트 6 + 글 6 — 아이콘이 있어도 가장자리 ↔ 아이콘 12 | 14px | 14px | 14px — 누르는 영역 24 × 24 | 14px | ✓ · ✓ | 32 — 촘촘한 줄(1280 이상 데스크톱의 필터 · 표 위) |
medium (기본) | 36px — 웹 rem — 큰 글자에서 배율대로. 앱은 최소 높이 — 글을 따라 늘어난다(label 비고) | spacing-x3_5 14px — SEED 루트 8 + 글 6 | 16px | 14px | 14px — 누르는 영역 24 × 24 | 16px | ✓ · ✓ | 36 — 기본(폰 폼 포함) |
large | 40px — 웹 rem — 큰 글자에서 배율대로. 앱은 최소 높이 — 글을 따라 늘어난다(label 비고) | spacing-x4 16px — SEED 루트 10 + 글 6 | 16px | 16px | 16px — 누르는 영역 24 × 24 | 16px | ✓ · ✓ | 40 — 화면의 주인공 고르기 |
큰 글자
글은 글자 크기 설정을 따르고, 글이 상자를 넘지 않는다. 상자가 커지는 방법은 플랫폼마다 다르다(2026-10-17 사용자 결정 — 03-E 결정 1 C).
- 웹 — 높이 · 여백 · 아이콘 · 지우기가 rem 이라 글자 크기 설정의 배율대로 커진다. 200% 에서 medium 칩 72 · 지우기 28.
- 앱 — 높이가 최소 높이다. 글이 커지면 칩이 글 줄 높이 + 위아래 (높이 − 19) ÷ 2 로 늘어나고(medium 200% 에서 38 + 8.5 × 2 = 55), 좌우 여백 · 아이콘 · 지우기는 그대로다. 높이를 고정해 글이 상자를 넘게 두지 않는다.
같은 설정에서 웹 칩이 앱보다 크다(72 대 55). 보통 글자(100%)에서는 두 플랫폼 모두 32 · 36 · 40 이다. 앱 상자에도 배율을 곱하는 것(A) · 두 플랫폼 모두 px 최소 크기(B — SEED 는 상자 px · 글자 1.5배 상한)는 고르지 않았다.
State
| 상태 | 모습 |
|---|---|
enabled | 변형 · 고름의 바탕 |
hovered | 웹 — 누름과 같은 바탕(축소 없음) |
pressed | 누름 바탕(Solid bg-neutral-weak-alpha-pressed · Outline bg-layer-default-pressed · 고른 Outline Weak bg-neutral-weak-pressed · 짙은 채움 bg-neutral-inverted-pressed) + 칩 전체 2px 거리 축소(v104) |
focused | 키보드 포커스에만 바깥 링 2px · 띄움 2px stroke-focus-ring |
disabled | 바탕 bg-disabled · 글자 fg-disabled — 흐리게 하지 않는다(v106). Solid(안 고름)는 바탕 bg-neutral-weak-alpha 를 그대로 두고 글 · 아이콘만 fg-disabled 다 — bg-disabled 는 회색 바닥과 같은 색이라 알약이 사라진다(2026-10-17 사용자 결정 — 03-B 결정 1 A). 고른 채 막히면 짙은 1px stroke-neutral-solid 를 남겨 무엇을 골랐는지 보인다 |
상태 — Outline Weak
| 상태 | 배경 | 글자·아이콘 | 테두리 | 테두리 두께 | 배율 | 커서 | 축소 시간 | 축소 곡선 | 링 두께 | 링 간격 | 링 색 |
|---|---|---|---|---|---|---|---|---|---|---|---|
enabled 기본 | transparent | color-fg-neutral #1A1F2E · 다크 #F5F6FA | color-stroke-neutral-weak #E5E8EF · 다크 #404757 — SEED stroke.neutral-muted 의 불투명 짝 — 안쪽 1px(inset) | 1px | — | pointer | — | — | — | — | — |
hovered 웹 — 누름 바탕과 같다(v106), 축소는 없다 | color-bg-layer-default-pressed #F7F8FD · 다크 #353B4D | color-fg-neutral #1A1F2E · 다크 #F5F6FA | color-stroke-neutral-weak #E5E8EF · 다크 #404757 — SEED stroke.neutral-muted 의 불투명 짝 — 안쪽 1px(inset) | 1px | — | pointer | — | — | — | — | — |
pressed 누름 바탕 + 칩 전체를 2px 거리로 축소(v104) | color-bg-layer-default-pressed #F7F8FD · 다크 #353B4D | color-fg-neutral #1A1F2E · 다크 #F5F6FA | color-stroke-neutral-weak #E5E8EF · 다크 #404757 — SEED stroke.neutral-muted 의 불투명 짝 — 안쪽 1px(inset) | 1px | 칩 전체 2px 거리 축소 — 기준 길이 max(높이, 폭 ÷ 4, 24) 에서 2px(SEED scaleScope: self · v104) — 모션 줄이기면 하지 않는다 | pointer | motion-duration-pressed-scale 150ms | motion-ease-pressed-scale cubic-bezier(0, 0, 0.15, 1) | — | — | — |
focused 웹 — 키보드 포커스에만 링 | transparent | color-fg-neutral #1A1F2E · 다크 #F5F6FA | color-stroke-neutral-weak #E5E8EF · 다크 #404757 — SEED stroke.neutral-muted 의 불투명 짝 — 안쪽 1px(inset) | 1px | — | pointer | — | — | 2px | 2px | color-stroke-focus-ring #1A1F2E · 다크 #F5F6FA |
disabled 전용 색(v106) — 불투명도로 흐리게 하지 않는다 | color-bg-disabled #F5F6FA · 다크 #353B4D | color-fg-disabled #8A91A0 · 다크 #838997 | color-stroke-neutral-weak #E5E8EF · 다크 #404757 — SEED stroke.neutral-muted 의 불투명 짝 — 안쪽 1px(inset) | 1px | — | not-allowed — 누름 축소 · 누름 바탕 없음 | — | — | — | — | — |
상태 — Outline Weak 고름
| 상태 | 배경 | 글자·아이콘 | 테두리 | 테두리 두께 | 배율 | 커서 | 축소 시간 | 축소 곡선 | 링 두께 | 링 간격 | 링 색 |
|---|---|---|---|---|---|---|---|---|---|---|---|
enabled 기본 | color-bg-neutral-weak #F5F6FA · 다크 #353B4D | color-fg-neutral #1A1F2E · 다크 #F5F6FA | color-stroke-neutral-contrast #1A1F2E · 다크 #F5F6FA — 고름 — 짙은 1px(v113) | 1px | — | pointer | — | — | — | — | — |
hovered 웹 — 누름 바탕과 같다(v106), 축소는 없다 | color-bg-neutral-weak-pressed #EDEFF3 · 다크 #404757 | color-fg-neutral #1A1F2E · 다크 #F5F6FA | color-stroke-neutral-contrast #1A1F2E · 다크 #F5F6FA — 고름 — 짙은 1px(v113) | 1px | — | pointer | — | — | — | — | — |
pressed 누름 바탕 + 칩 전체를 2px 거리로 축소(v104) | color-bg-neutral-weak-pressed #EDEFF3 · 다크 #404757 | color-fg-neutral #1A1F2E · 다크 #F5F6FA | color-stroke-neutral-contrast #1A1F2E · 다크 #F5F6FA — 고름 — 짙은 1px(v113) | 1px | 칩 전체 2px 거리 축소 — 기준 길이 max(높이, 폭 ÷ 4, 24) 에서 2px(SEED scaleScope: self · v104) — 모션 줄이기면 하지 않는다 | pointer | motion-duration-pressed-scale 150ms | motion-ease-pressed-scale cubic-bezier(0, 0, 0.15, 1) | — | — | — |
focused 웹 — 키보드 포커스에만 링 | color-bg-neutral-weak #F5F6FA · 다크 #353B4D | color-fg-neutral #1A1F2E · 다크 #F5F6FA | color-stroke-neutral-contrast #1A1F2E · 다크 #F5F6FA — 고름 — 짙은 1px(v113) | 1px | — | pointer | — | — | 2px | 2px | color-stroke-focus-ring #1A1F2E · 다크 #F5F6FA |
disabled 전용 색(v106) — 불투명도로 흐리게 하지 않는다 | color-bg-disabled #F5F6FA · 다크 #353B4D | color-fg-disabled #8A91A0 · 다크 #838997 | color-stroke-neutral-solid #767C8B · 다크 #838997 — 고른 채 막힘 — 짙은 1px 를 회색으로 남긴다 | 1px | — | not-allowed — 누름 축소 · 누름 바탕 없음 | — | — | — | — | — |
상태 — Solid
| 상태 | 배경 | 글자·아이콘 | 배율 | 커서 | 축소 시간 | 축소 곡선 | 링 두께 | 링 간격 | 링 색 |
|---|---|---|---|---|---|---|---|---|---|
enabled 기본 | color-bg-neutral-weak-alpha #0000000C · 다크 #FFFFFF20 — SEED 그대로 투명(검정 4.7% · 다크 흰 12.5%) — 놓인 바탕에 섞여 회색 바닥 위 1.11 · 흰 위 1.11 · 다크 1.47:1(v120) | color-fg-neutral #1A1F2E · 다크 #F5F6FA | — | pointer | — | — | — | — | — |
hovered 웹 — 누름 바탕과 같다(v106), 축소는 없다 | color-bg-neutral-weak-alpha-pressed #00000010 · 다크 #FFFFFF2E | color-fg-neutral #1A1F2E · 다크 #F5F6FA | — | pointer | — | — | — | — | — |
pressed 누름 바탕 + 칩 전체를 2px 거리로 축소(v104) | color-bg-neutral-weak-alpha-pressed #00000010 · 다크 #FFFFFF2E | color-fg-neutral #1A1F2E · 다크 #F5F6FA | 칩 전체 2px 거리 축소 — 기준 길이 max(높이, 폭 ÷ 4, 24) 에서 2px(SEED scaleScope: self · v104) — 모션 줄이기면 하지 않는다 | pointer | motion-duration-pressed-scale 150ms | motion-ease-pressed-scale cubic-bezier(0, 0, 0.15, 1) | — | — | — |
focused 웹 — 키보드 포커스에만 링 | color-bg-neutral-weak-alpha #0000000C · 다크 #FFFFFF20 — SEED 그대로 투명(검정 4.7% · 다크 흰 12.5%) — 놓인 바탕에 섞여 회색 바닥 위 1.11 · 흰 위 1.11 · 다크 1.47:1(v120) | color-fg-neutral #1A1F2E · 다크 #F5F6FA | — | pointer | — | — | 2px | 2px | color-stroke-focus-ring #1A1F2E · 다크 #F5F6FA |
disabled 전용 색(v106) — 불투명도로 흐리게 하지 않는다 | color-bg-neutral-weak-alpha #0000000C · 다크 #FFFFFF20 — 막혀도 바탕은 그대로 — 글 · 아이콘만 fg-disabled(공통). bg-disabled(gray-200)는 회색 바닥(bg-layer-basement, 같은 gray-200)과 1.00:1 이라 알약이 사라진다. 투명 바탕은 회색 바닥 위 1.11 · 흰 위 1.11 · 다크 1.47:1. 안 고른 칩과는 글 색으로 갈린다(SEED 도 바탕을 바꾸지 않는다 — 2026-10-17 사용자 결정 03-B 결정 1 A) | color-fg-disabled #8A91A0 · 다크 #838997 | — | not-allowed — 누름 축소 · 누름 바탕 없음 | — | — | — | — | — |
상태 — Solid 고름
| 상태 | 배경 | 글자·아이콘 | 테두리 | 테두리 두께 | 배율 | 커서 | 축소 시간 | 축소 곡선 | 링 두께 | 링 간격 | 링 색 |
|---|---|---|---|---|---|---|---|---|---|---|---|
enabled 기본 | color-bg-neutral-inverted #1A1F2E · 다크 #F5F6FA | color-fg-neutral-inverted #FFFFFF · 다크 #242938 | — | — | — | pointer | — | — | — | — | — |
hovered 웹 — 누름 바탕과 같다(v106), 축소는 없다 | color-bg-neutral-inverted-pressed #535866 · 다크 #B7BDCC | color-fg-neutral-inverted #FFFFFF · 다크 #242938 | — | — | — | pointer | — | — | — | — | — |
pressed 누름 바탕 + 칩 전체를 2px 거리로 축소(v104) | color-bg-neutral-inverted-pressed #535866 · 다크 #B7BDCC | color-fg-neutral-inverted #FFFFFF · 다크 #242938 | — | — | 칩 전체 2px 거리 축소 — 기준 길이 max(높이, 폭 ÷ 4, 24) 에서 2px(SEED scaleScope: self · v104) — 모션 줄이기면 하지 않는다 | pointer | motion-duration-pressed-scale 150ms | motion-ease-pressed-scale cubic-bezier(0, 0, 0.15, 1) | — | — | — |
focused 웹 — 키보드 포커스에만 링 | color-bg-neutral-inverted #1A1F2E · 다크 #F5F6FA | color-fg-neutral-inverted #FFFFFF · 다크 #242938 | — | — | — | pointer | — | — | 2px | 2px | color-stroke-focus-ring #1A1F2E · 다크 #F5F6FA |
disabled 전용 색(v106) — 불투명도로 흐리게 하지 않는다 | color-bg-disabled #F5F6FA · 다크 #353B4D | color-fg-disabled #8A91A0 · 다크 #838997 | color-stroke-neutral-solid #767C8B · 다크 #838997 — 고른 채 막힘 — 회색 채움에 짙은 1px 를 남겨 안 고른 칩과 가른다 | 1px | — | not-allowed — 누름 축소 · 누름 바탕 없음 | — | — | — | — | — |
상태 — Outline Strong 고름
| 상태 | 배경 | 글자·아이콘 | 테두리 | 테두리 두께 | 배율 | 커서 | 축소 시간 | 축소 곡선 | 링 두께 | 링 간격 | 링 색 |
|---|---|---|---|---|---|---|---|---|---|---|---|
enabled 기본 | color-bg-neutral-inverted #1A1F2E · 다크 #F5F6FA | color-fg-neutral-inverted #FFFFFF · 다크 #242938 | color-stroke-neutral-weak #E5E8EF · 다크 #404757 — SEED stroke.neutral-muted 의 불투명 짝 — 안쪽 1px(inset) | 0px — 짙은 채움 위 테두리는 지운다(SEED Chip Tabs 와 같다) | — | pointer | — | — | — | — | — |
hovered 웹 — 누름 바탕과 같다(v106), 축소는 없다 | color-bg-neutral-inverted-pressed #535866 · 다크 #B7BDCC | color-fg-neutral-inverted #FFFFFF · 다크 #242938 | color-stroke-neutral-weak #E5E8EF · 다크 #404757 — SEED stroke.neutral-muted 의 불투명 짝 — 안쪽 1px(inset) | 0px — 짙은 채움 위 테두리는 지운다(SEED Chip Tabs 와 같다) | — | pointer | — | — | — | — | — |
pressed 누름 바탕 + 칩 전체를 2px 거리로 축소(v104) | color-bg-neutral-inverted-pressed #535866 · 다크 #B7BDCC | color-fg-neutral-inverted #FFFFFF · 다크 #242938 | color-stroke-neutral-weak #E5E8EF · 다크 #404757 — SEED stroke.neutral-muted 의 불투명 짝 — 안쪽 1px(inset) | 0px — 짙은 채움 위 테두리는 지운다(SEED Chip Tabs 와 같다) | 칩 전체 2px 거리 축소 — 기준 길이 max(높이, 폭 ÷ 4, 24) 에서 2px(SEED scaleScope: self · v104) — 모션 줄이기면 하지 않는다 | pointer | motion-duration-pressed-scale 150ms | motion-ease-pressed-scale cubic-bezier(0, 0, 0.15, 1) | — | — | — |
focused 웹 — 키보드 포커스에만 링 | color-bg-neutral-inverted #1A1F2E · 다크 #F5F6FA | color-fg-neutral-inverted #FFFFFF · 다크 #242938 | color-stroke-neutral-weak #E5E8EF · 다크 #404757 — SEED stroke.neutral-muted 의 불투명 짝 — 안쪽 1px(inset) | 0px — 짙은 채움 위 테두리는 지운다(SEED Chip Tabs 와 같다) | — | pointer | — | — | 2px | 2px | color-stroke-focus-ring #1A1F2E · 다크 #F5F6FA |
disabled 전용 색(v106) — 불투명도로 흐리게 하지 않는다 | color-bg-disabled #F5F6FA · 다크 #353B4D | color-fg-disabled #8A91A0 · 다크 #838997 | color-stroke-neutral-solid #767C8B · 다크 #838997 — 고른 채 막힘 — 짙은 1px 로 안 고른 칩과 가른다 | 1px | — | not-allowed — 누름 축소 · 누름 바탕 없음 | — | — | — | — | — |
상태 — 입력값 칩의 지우기 · 묶음
| 상태 | removeButton 배율 | group 외곽선 | group 외곽선 두께 | group 외곽선 간격 |
|---|---|---|---|---|
enabled 기본 | — | — | — | — |
pressed 누름 바탕 + 칩 전체를 2px 거리로 축소(v104) | 지우기 2px 거리 축소 — 입력값 칩의 지우기만 따로 준다(기준 24 — SEED scaleScope: self, Input Button 의 지우기와 같다). 칩은 누름이 아니다 | — | — | — |
focused 웹 — 키보드 포커스에만 링 | — | color-stroke-focus-ring #1A1F2E · 다크 #F5F6FA | 2px — 묶음이 포커스를 받았을 때(입력값을 다 지운 뒤) — 키보드 포커스에만, 모서리 없이 묶음 둘레 | 2px |
묶음
| 속성 | 값 | 비고 |
|---|---|---|
| 간격 | spacing-between-chips 8px | 칩 사이 — 줄바꿈 묶음은 줄 사이도 8(SEED 예제) |
| 줄 간격 | spacing-between-chips 8px | |
| 최소 높이 | 36px | 비었을 때만 — 입력값을 다 지우면 포커스가 묶음으로 오므로 링이 납작한 선이 되지 않게 칩 한 줄(medium) 높이를 남긴다 |
가로 스크롤 줄
| 속성 | 값 | 비고 |
|---|---|---|
| 좌우 여백 | spacing-global-gutter 24px | 줄을 화면 끝까지 내고 안쪽 여백을 화면 여백만큼 — 스크롤해도 첫 칩이 여백에서 시작한다. 이미 화면 여백 안에 있으면 바깥 −24 로 화면 끝까지 낸다(bleed) |
| 상하 여백 | spacing-x1_5 6px | 스크롤 칸은 넘친 것을 자르므로 — 누르는 영역 44 · 포커스 링이 잘리지 않게 |
| 상하 바깥 여백 | −6px | 안쪽 위아래 6 을 바깥에서 되돌려 줄 높이는 칩 그대로다. 줄을 두 겹(바깥 묶음 · 안쪽 스크롤 칸)으로 둬 부모의 위아래 간격(space-y · gap)이 지워지지 않게 한다 |
| 넘칠 때 | auto | 스크롤바는 숨긴다 |
| 끝 흐림 | 좌우 20px | Scroll Fog row(scroll-fog.yaml) — gradient-fade-mask 마스크, 늘 켜짐. 안쪽 여백 24 가 흐림보다 넓어 처음 · 끝의 칩은 흐리지 않는다(2026-10-03) |
| 스크롤 여유 | spacing-global-gutter 24px | 키보드로 칩을 옮겨도 화면 여백 안에 멈춘다 |
모션
| 전환 | 시간 | 곡선 | 대상 | 비고 |
|---|---|---|---|---|
누름 · 호버 · 고름 — 색 | motion-duration-color-transition 150ms | motion-ease-easing cubic-bezier(0.35, 0, 0.35, 1) | background-color, color, box-shadow | |
누름 — 칩 | motion-duration-pressed-scale 150ms | motion-ease-pressed-scale cubic-bezier(0, 0, 0.15, 1) | scale | 칩 전체 2px 거리 축소 — 모션 줄이기면 하지 않는다 |
쓰임 넷
| 쓰임 | 칩 | 의미 | 고름 |
|---|---|---|---|
| 고르기 — 하나 | ChipRadio 묶음 | 라디오(radiogroup) — 화살표로 옮기면 고른다 | 다시 눌러도 풀리지 않는다 |
| 고르기 — 여럿 | ChipToggle | 체크박스 | 다시 누르면 풀린다 |
| 제안 · 필터 바의 여는 칩 | Chip | 버튼 — 여는 칩은 aria-haspopup="dialog" | 제안은 고른 모습이 없다. 걸린 조건의 여는 칩은 고른 모습(짙은 채움) |
| 입력값 | InputChip | 글 + "{글} 지우기" 버튼 | Outline Weak 고른 모습 + 뒤 지우기 |
aria-pressed 는 쓰지 않는다(SEED) — 켜고 끄는 단추 하나는 Toggle(아이콘 단추 — 2026-10-09)이다.
Guidelines
하나 고르기 — "전체" · "없음" 은 선택지로
하나 고르기 칩은 라디오다 — 고른 칩을 다시 눌러도 풀리지 않고, 늘 하나가 골라져 있다. 거르기의 "전체" 는 맨 앞 선택지로 둔다(글은 "전체" 하나 — "혜택 전체" 처럼 바꾸지 않는다). 칩으로 거르는 축은 태그처럼 개수가 바뀌거나 5개 이상인 축이다 — 개수가 정해진 2 ~ 4가지 보기(프리셋 정렬 많이 쓴 순 · 최근 사용 · 이름순)는 Segmented Control(그 차례에)이다. 폼은 기본값을 골라 두거나, "없음" 이 답이면 "{칸 이름} 없음" 을 맨 앞에 둔다(Select 와 같은 규칙).
여럿 고르기 — 다른 칩을 바꾸는 칩을 두지 않는다
여럿 고르기 칩은 체크박스다 — 다시 누르면 풀린다. "전체 선택" 처럼 다른 칩을 바꾸는 칩은 두지 않는다. 거르기에서 하나도 안 고르면 "조건 없음"(전부 보인다)이고, 폼에서 꼭 골라야 하면 Field 의 오류로 알린다. 몇 개까지 고를 수 있는지는 Field 설명에 적는다.
필터 바 — 조건마다 칩
목록 위 한 줄(가로 스크롤 · 끝 흐림)에 조건마다 칩을 하나씩 둔다. 칩은 뒤에 아래 화살표를 달고, 누르면 그 조건만 시트(1280 미만) · 팝오버(1280 이상)로 연다. 걸린 조건의 칩은 고른 모습(짙은 채움)에 값을 요약하고("식비 외 2개" — Select 의 여럿 고른 값과 같은 꼴), 하나라도 걸리면 맨 앞에 지우기 칩(↺, 아이콘만 — 이름 "필터 지우기")을 둔다. 걸린 조건 칩의 글이 곧 지금 조건이라 따로 "필터 2" 같은 개수를 두지 않는다.
빼기 — 칩은 두 상태만
칩은 고름 · 안 고름 둘뿐이다 — 누를 때마다 고름 → 빼고 → 해제를 도는 3상태 칩을 두지 않는다. 빼는 조건이 필요하면 조건마다 "고른 것만 · 고른 것 빼고" 를 먼저 고르고(하나 고르기 칩 둘), 아래에서 여럿 고른다 — 한 조건 안에서 넣기 · 빼기를 섞지 않는다.
제안 — 고른 표시가 없다
제안 칩(빠른 금액 · 빠른 기간)은 누르면 칸에 값을 넣는 버튼이다 — 고른 모습이 없고, 지금 값은 칸이 보인다. 다시 누르면 같은 값을 다시 넣는다(고친 값을 덮어쓰지 않게, 여러 칸을 채우는 제안은 칸을 비웠을 때만 채우거나 덮어쓰기 전에 묻는다). 프리셋 칩은 제안이 아니다 — 다시 누르면 해제하는 토글이라 적용한 칩만 고른 모양이고, 목록 제목이 "{이름} 적용됨" 으로 함께 알린다(2026-10-31).
Solid 는 어느 바탕에서나
Solid 의 옅은 바탕은 투명한 bg-neutral-weak-alpha 라 흰 표면에서도, 회색 바닥(bg-layer-basement) 위에서도 보인다(1.11:1 · 다크 1.47:1 — v120). 불투명 bg-neutral-weak 로 칠하면 회색 바닥과 같은 색이라 칩이 사라진다 — 칩 바탕에 불투명 약한 배경을 쓰지 않는다(DESIGN.md Elevation 의 "바닥 위의 채움", 2026-10-16 사용자 결정 — 기초 웹 01-040 B). 막힌 Solid 칩도 같다 — 바탕은 그대로 두고 글 · 아이콘만 fg-disabled 로 바꾼다(bg-disabled 도 회색 바닥과 같은 gray-200 — 2026-10-17 사용자 결정 03-B 결정 1 A). 막힌 칩과 안 고른 칩은 바탕이 아니라 글 색으로 갈린다. 회색 바닥 위 줄에서 막힌 칩을 숨기는 규칙(B) · bg-disabled 에 1px 테두리(C)는 고르지 않았다.
글
- 명사로 짧게, 한 줄 — 칩은 줄바꿈하지 않고 글만큼 넓어진다. 한 묶음의 글 길이 · 말투를 맞춘다.
- 여럿을 한 칩에 줄이면 "식비 외 2개"(첫 값 + 나머지 수 — "외" 는 앞의 값을 뺀 수). 개수만 쓰면 "3개 고름".
- 코드값(
Y·N·ADMIN)을 글로 내지 않는다(Writing).
줄보다 긴 칩 — 줄 폭에서 말줄임
넣은 값 · 사람 이름처럼 사용자가 친 글은 길이를 고를 수 없고, 큰 글자에서는 짧은 글도 길어진다. 칩이 놓인 줄보다 넓어지면 칩은 줄 폭에서 멈추고 글 끝을 "…" 로 줄인다 — 앞 · 뒤 아이콘과 입력값 칩의 지우기 × 는 줄지 않고 남는다. 가로 스크롤 줄(필터 바 · 제안 줄)과 Chip Tabs 도 같다 — 칩 하나는 보이는 줄 폭(화면 여백 안)을 넘지 않는다(2026-10-17 사용자 결정 — 03-E 후속). 여는 칩의 아래 화살표도 남는다. 보조 기술 · 지우기 이름("{글} 지우기")은 글 전체를 읽고, 넣은 값은 입력칸에서 다시 볼 수 있다. 줄보다 짧은 칩은 그대로 글만큼 넓다(2026-10-17 사용자 결정 — 03-E 결정 2 A). 칩 안에서 줄바꿈(B — 칩끼리 높이가 갈린다) · 큰 글자에서 가로 스크롤 줄로 바꾸기(C)는 고르지 않았다.
묶음 배치
칩 사이는 8(spacing-between-chips)이다. 폼 · 시트 안의 고르기 묶음은 줄바꿈하고(줄 사이 8), 목록 위 필터 바 · 제안 줄은 한 줄 가로 스크롤로 둔다 — 줄을 화면 끝까지 내고 안쪽 여백을 화면 여백(spacing-global-gutter)만큼 둬 스크롤해도 첫 칩이 여백에서 시작한다(이미 화면 여백 안에 두는 코드는 bleed 로 줄을 화면 끝까지 낸다). 줄의 양 끝은 Scroll Fog 로 늘 흐린다 — 좌우 20, 스크롤 위치와 상관없이 켜져 있고, 안쪽 여백(화면 여백 24)이 흐림보다 넓어 처음 · 끝의 칩은 흐리지 않는다.
탭 · Segmented 와 나누기
칩은 값을 고르거나 거르는 자리다. 다른 구역으로 옮기는 2차 탭은 Tabs 의 칩 모양(Chip Tabs), 같은 내용을 2 ~ 4가지로 바로 거르거나 다르게 보는 자리는 Segmented Control 이다(그 차례에). 한 화면에 칩 모양 탭과 필터 칩이 같이 있으면 탭을 Line 으로 둔다 — 같은 모양이 둘이면 무엇이 탭인지 알 수 없다.
| 이런 자리 | 컴포넌트 |
|---|---|
| 2 ~ 4개 짧은 폼 값 | Chip(하나 · 여럿) |
| 누르면 값을 채운다 | Chip(제안) |
| 목록 조건을 걸고 푼다 | Chip(필터 바) |
| 넣은 값을 보이고 하나씩 뺀다 | Chip(입력값) |
| 5개 이상 · 글이 긴 2 ~ 4개 | Select · Radio · Checkbox |
| 다른 구역으로 옮긴다(2차) | Tabs 의 Chip Tabs(그 차례에) |
| 같은 내용 2 ~ 4가지 보기 · 정렬 | Segmented Control(그 차례에) |
| 누를 수 없는 상태 · 분류 · 메타 | Badge · Tag Group |
건수 · 큰 글자
- 건수 — 하나 고르기 칩의 건수("업무 5")는 글자와 다른 색(
fg-neutral-subtle, 고른 칩은 고른 글자 색)으로 뒤에 붙인다. - 큰 글자 — 글이 있는 칩의 높이는 글자 크기를 따른다. 위아래 여백 = (높이 − 줄 높이 19) ÷ 2 — 글자 100% 에서는 정한 높이 그대로이고, 200% 에서 글이 위아래에 붙지 않는다.
코드
레시피 recipes/shadcn/components/ui/chip.tsx 를 쓴다. 고르기 묶음은 Field 안에 둔다(라벨이 묶음의 이름). 아래 미리보기는 스펙 값으로 그린 모습이다.
하나 고르기
import { Field } from "@/components/ui/field"
import { ChipRadio, ChipRadioGroup } from "@/components/ui/chip"
<Field label="거래 종류">
<ChipRadioGroup value={type} onValueChange={setType}>
<ChipRadio variant="outlineStrong" value="expense">지출</ChipRadio>
<ChipRadio variant="outlineStrong" value="income">수입</ChipRadio>
<ChipRadio variant="outlineStrong" value="transfer">이체</ChipRadio>
</ChipRadioGroup>
</Field>여럿 고르기
import { ChipGroup, ChipToggle } from "@/components/ui/chip"
<Field label="알림" description="고른 때마다 알려줘요.">
<ChipGroup>
{["당일", "1일 전", "3일 전", "1주 전"].map((t) => (
<ChipToggle key={t} checked={alarms.includes(t)} onCheckedChange={(on) => toggle(t, on)}>
{t}
</ChipToggle>
))}
</ChipGroup>
</Field>필터 바
import { ChevronDown, RotateCcw } from "lucide-react"
import { Chip, ChipGroup } from "@/components/ui/chip"
<ChipGroup layout="scroll" bleed aria-label="거래 거르기">
{active > 0 && <Chip variant="outlineStrong" layout="iconOnly" aria-label="필터 지우기" onClick={reset}><RotateCcw /></Chip>}
<Chip variant="solid" selected={!!period} suffixIcon={<ChevronDown />} aria-haspopup="dialog" onClick={() => open("period")}>
{period ? periodLabel : "기간"}
</Chip>
<Chip variant="solid" selected={cats.length > 0} suffixIcon={<ChevronDown />} aria-haspopup="dialog" onClick={() => open("category")}>
{cats.length ? summarize(cats) : "카테고리"}
</Chip>
</ChipGroup>제안 · 입력값
import { Chip, ChipGroup, InputChip } from "@/components/ui/chip"
<ChipGroup aria-label="빠른 금액">
{[100000, 300000, 500000].map((v) => (
<Chip key={v} variant="solid" onClick={() => setAmount(v)}>{formatMan(v)}</Chip>
))}
</ChipGroup>
<ChipGroup aria-label="참여자">
{people.map((p) => <InputChip key={p.id} onRemove={() => removePerson(p.id)}>{p.name}</InputChip>)}
</ChipGroup>Behavior
| 인터랙션 | 동작 |
|---|---|
| 하나 고르기 Click · Tap | 그 칩을 고른다. 고른 칩을 다시 눌러도 그대로다. |
하나 고르기 ← → ↑ ↓ | 묶음 안에서 옮기며 고른다(라디오). Tab 은 고른 칩 하나에만 선다. |
하나 고르기 Home · End | 받지 않는다 — 초점도 고른 칩도 그대로, 화면도 스크롤되지 않는다(PageUp · PageDown 도). 첫 · 끝 칩으로는 화살표로 간다(SEED · 진짜 라디오 · WAI-ARIA APG Radio Group 과 같다 — 2026-10-17 사용자 결정 03-E 결정 3 A). Tabs 는 Home · End 로 옮기며 고른다 — 키가 다르다. |
여럿 고르기 Click · Space | 고르거나 푼다. 칩마다 Tab 이 선다. |
제안 · 여는 칩 Click · Enter · Space | 값을 넣거나(제안) 그 조건의 시트 · 팝오버를 연다. |
| 입력값 지우기 | 그 값만 뺀다. 포커스는 다음 칩의 지우기(없으면 앞 칩의 지우기, 그것도 없으면 묶음 — 묶음도 키보드 링을 그린다)로 간다. 지우기에 키보드 포커스가 있으면 링은 칩 둘레에 그린다. |
| 마우스 호버 | 누름과 같은 바탕(축소 없음). |
| Disabled | 누를 수 없다 · 커서 not-allowed · Tab 이 서지 않는다. Solid 는 바탕이 그대로이고 글 · 아이콘만 흐려진다. 고른 채 막히면 짙은 1px 테두리가 남는다. |
Accessibility
| 기준 | 검증 |
|---|---|
| WCAG 1.4.3 Color contrast(글자 ≥ 4.5:1) | 안 고른 글 fg-neutral 흰 표면 위 16.41 · 13.42, Solid 투명 바탕 위 라이트 13.71 ~ 14.79 · 다크 7.84 ~ 10.33(놓인 바탕에 따라 — v120), 고른 짙은 채움 위 fg-neutral-inverted 16.41 · 13.42 ✓. 비활성 fg-disabled 는 기준 밖(비활성 UI) |
| WCAG 1.4.11 Non-text contrast(≥ 3:1) | 고름은 짙은 채움(바탕과 16.41 · 13.42) 또는 짙은 1px(16.41 · 13.42)로 안 고름과 가른다 ✓. 고른 채 막힘 stroke-neutral-solid 은 bg-disabled 위 3.87 · 3.18 ✓(비활성이라 기준 밖이지만 3:1 을 넘긴다). 안 고른 칩의 경계(Solid 바탕 1.11 · 다크 1.47 — 회색 바닥 위에서도 · Outline 1px 1.23)는 칩을 알리는 유일한 표시가 아니다 — 글이 알린다(SEED 와 같다). 키보드 포커스 링 Desk 8.38 · 6.10 · HR 8.17 · 6.07 ✓ |
| WCAG 1.4.4 Resize text | 글이 글자 크기 설정을 따르고 상자를 넘지 않는다 ✓ — 웹은 상자도 배율대로(rem), 앱은 최소 높이가 글을 따라 늘어난다. 줄보다 긴 칩은 줄 폭에서 말줄임(글 전체는 보조 기술이 읽는다) |
| WCAG 2.4.7 Focus visible | 키보드 포커스에 바깥 링 2px · 띄움 2px |
| WCAG 2.5.8 Target Size — Minimum(AA ≥ 24×24) | 모든 크기 ✓(가장 작은 small 32 · 최소 폭 44). 입력값 칩의 지우기는 누르는 영역 24 × 24 |
| WCAG 2.5.5 Target Size — Enhanced(AAA ≥ 44×44) | 누르는 영역을 가로 · 세로 44 까지 넓힌다 ✓(보이는 칩 32 · 36 · 40, 아이콘만 있는 칩도) — 줄바꿈 묶음에서 small 만 위아래 줄의 영역이 4 겹친다. 입력값 칩의 지우기는 24 × 24 라 AAA 밖이다 |
| ARIA | 하나 고르기 role="radiogroup" + 라디오(묶음 이름은 Field 라벨 · aria-label), 여럿 고르기 체크박스, 제안 · 여는 칩 <button>(여는 칩 aria-haspopup="dialog"), 입력값 지우기 "{글} 지우기". aria-pressed 는 쓰지 않는다. 아이콘만 있는 칩은 aria-label 필수 |
Do / Don't
✅ Do
- 2 ~ 4개 짧은 폼 값은 칩으로 — 고르기 묶음은 Field 로 감싸 이름을 단다.
- 하나 고르기의 "전체" 는 맨 앞 선택지로, 폼은 기본값을 골라 둔다.
- 필터 바는 조건마다 칩 하나, 걸린 조건은 고른 모습 + 값 요약.
- 고른 칩은 중립색으로.
- Solid 바탕은 투명한
bg-neutral-weak-alpha로 — 회색 바닥 위에서도 보인다.
❌ Don't
- 고른 칩을 브랜드 색으로 칠하기.
- "전체 선택" 처럼 다른 칩을 바꾸는 칩.
- 누를 때마다 고름 → 빼고 → 해제를 도는 3상태 칩.
- 제안 칩을 고른 모습으로 남기기.
- 칩 모양 탭과 필터 칩을 한 화면에 같은 모양으로.
- 누를 수 없는 표시를 칩 모양으로(Badge).
Specification
chip.yaml 의 규칙을 하나도 빼지 않고 조건마다 그린다 — 웹 · 앱이 Chip 을 만들 때 이 값을 그대로 쓴다. 조건이 없는 Base 가 모든 조합에 걸리고, 뒤의 규칙이 앞의 같은 값을 덮는다. 상태는 enabled 에서 바뀌는 값만 적었다.
Base
| 부위 | 상태 | 속성 | 값 |
|---|---|---|---|
root | enabled | 최대 너비maxWidth | 100%놓인 줄의 폭 — 줄바꿈 묶음은 그 줄 폭, 가로 스크롤 줄(필터 바 · 제안 줄)과 Chip Tabs 는 보이는 줄 폭(화면 여백 안 — 2026-10-17 사용자 결정 03-E 후속). 넣은 값 · 사람 이름 · 큰 글자로 칩이 줄보다 넓어지면 줄 폭에서 멈추고 글 끝을 말줄임(…)한다. 앞 · 뒤 아이콘과 입력값 칩의 지우기 × 는 줄지 않고 남는다. 줄보다 짧은 칩은 그대로 글만큼 넓다. 칩 안 줄바꿈 · 큰 글자에서 가로 스크롤 줄로 바꾸기는 고르지 않았다(2026-10-17 사용자 결정 — 03-E 결정 2 A) |
| 간격gap | spacing-x1_56px아이콘 ↔ 글(SEED label paddingX 6) | ||
| 모서리radius | radius-full9999px(알약) | ||
| 커서cursor | pointer | ||
| 터치 영역touchTarget | 44 × 44보이는 칩과 따로 누르는 영역을 가로 · 세로 44 까지 넓힌다(Button 과 같다 — 글이 있는 칩은 최소 폭 44 · 48 · 52 라 가로는 이미 44 이상이고, 아이콘만 있는 칩 32 · 36 · 40 은 가로도 44 로). AA ✓ · AAA ✓. 줄바꿈 묶음(줄 사이 8)에서 small 만 위아래 줄의 영역이 4 겹친다 | ||
| 전환 대상transitionProperty | background-color, color, box-shadow | ||
| 전환 시간transitionDuration | motion-duration-color-transition150ms | ||
| 전환 곡선transitionEasing | motion-ease-easingcubic-bezier(0.35, 0, 0.35, 1) | ||
label | enabled | 글자typography | text-t414px / 19px세 크기 모두 14 / 19 — 폰트 크기 설정을 따른다. 큰 글자에서 상자 — 웹은 rem 이라 높이 · 여백 · 아이콘 · 지우기가 배율대로 커진다(200% 에서 medium 72 · 지우기 28). 앱은 높이가 최소 높이라 글을 따라 늘어나고(글 줄 높이 + 위아래 (높이 − 19) ÷ 2 — medium 200% 에서 38 + 8.5 × 2 = 55), 여백 · 아이콘 · 지우기는 그대로다. 어느 쪽도 글이 상자를 넘지 않는다. 보통 글자(100%)에서는 두 플랫폼 모두 32 · 36 · 40 그대로(2026-10-17 사용자 결정 — 03-E 결정 1 C, 앱도 배율대로 · 두 플랫폼 px 최소 크기는 고르지 않았다) |
| 굵기fontWeight | 500 | ||
| 넘침overflow | 말줄임(…)칩이 줄 폭(root.maxWidth)에 닿을 때만 — 한 줄 그대로 끝을 줄인다. 보조 기술 · 지우기 이름("{글} 지우기")은 글 전체를 읽는다 | ||
removeButton | enabled | 지우기 색color | currentColor글자색 그대로 — 이름 "{글} 지우기", 누르는 영역 24 × 24, 칩 안에서 따로 눌린다(칩 자체는 버튼이 아니다). 호버 바탕은 없고 누르면 지우기만 따로 준다(아래 pressed — Input Button 의 지우기와 같다). 키보드 포커스 링은 지우기가 아니라 칩 둘레에 그린다 |
group | enabled | 최소 높이minHeight | 36px비었을 때만 — 입력값을 다 지우면 포커스가 묶음으로 오므로 링이 납작한 선이 되지 않게 칩 한 줄(medium) 높이를 남긴다 |
| 간격gap | spacing-between-chips8px칩 사이 — 줄바꿈 묶음은 줄 사이도 8(SEED 예제) | ||
| 줄 간격rowGap | spacing-between-chips8px | ||
scrollRow | enabled | 상하 여백paddingY | spacing-x1_56px스크롤 칸은 넘친 것을 자르므로 — 누르는 영역 44 · 포커스 링이 잘리지 않게 |
| 좌우 여백paddingX | spacing-global-gutter24px줄을 화면 끝까지 내고 안쪽 여백을 화면 여백만큼 — 스크롤해도 첫 칩이 여백에서 시작한다. 이미 화면 여백 안에 있으면 바깥 −24 로 화면 끝까지 낸다(bleed) | ||
| 상하 바깥 여백marginY | −6px안쪽 위아래 6 을 바깥에서 되돌려 줄 높이는 칩 그대로다. 줄을 두 겹(바깥 묶음 · 안쪽 스크롤 칸)으로 둬 부모의 위아래 간격(space-y · gap)이 지워지지 않게 한다 | ||
| 넘칠 때overflowX | auto스크롤바는 숨긴다 | ||
| 스크롤 여유scrollPadding | spacing-global-gutter24px키보드로 칩을 옮겨도 화면 여백 안에 멈춘다 | ||
| 끝 흐림fog | 좌우 20pxScroll Fog row(scroll-fog.yaml) — gradient-fade-mask 마스크, 늘 켜짐. 안쪽 여백 24 가 흐림보다 넓어 처음 · 끝의 칩은 흐리지 않는다(2026-10-03) | ||
root | pressed | 배율scale | 칩 전체 2px 거리 축소기준 길이 max(높이, 폭 ÷ 4, 24) 에서 2px(SEED scaleScope: self · v104) — 모션 줄이기면 하지 않는다 |
| 축소 시간scaleDuration | motion-duration-pressed-scale150ms | ||
| 축소 곡선scaleEasing | motion-ease-pressed-scalecubic-bezier(0, 0, 0.15, 1) | ||
removeButton | pressed | 배율scale | 지우기 2px 거리 축소입력값 칩의 지우기만 따로 준다(기준 24 — SEED scaleScope: self, Input Button 의 지우기와 같다). 칩은 누름이 아니다 |
focusRing | focused | 링 두께width | 2px |
| 링 색color | stroke-focus-ringDesk#0147AD다크 #7AA9F6HR#075B3C다크 #2ABE84 | ||
| 링 간격offset | 2px | ||
group | focused | 외곽선outlineColor | stroke-focus-ringDesk#0147AD다크 #7AA9F6HR#075B3C다크 #2ABE84 |
| 외곽선 두께outlineWidth | 2px묶음이 포커스를 받았을 때(입력값을 다 지운 뒤) — 키보드 포커스에만, 모서리 없이 묶음 둘레 | ||
| 외곽선 간격outlineOffset | 2px | ||
root | disabled | 배경background | bg-disabled#F5F6FA다크 #353B4D |
| 글자·아이콘foreground | fg-disabled#8A91A0다크 #838997 | ||
| 커서cursor | not-allowed누름 축소 · 누름 바탕 없음 |
size=small
| 부위 | 상태 | 속성 | 값 |
|---|---|---|---|
root | enabled | 높이height | 32px웹 rem — 큰 글자에서 배율대로. 앱은 최소 높이 — 글을 따라 늘어난다(label 비고) |
| 좌우 여백paddingX | spacing-x312pxSEED 루트 6 + 글 6 — 아이콘이 있어도 가장자리 ↔ 아이콘 12 | ||
prefixIcon | enabled | 앞 아이콘size | 14px |
suffixIcon | enabled | 뒤 아이콘size | 14px |
removeButton | enabled | 지우기 버튼size | 14px누르는 영역 24 × 24 |
icon | enabled | 아이콘size | 14px |
size=medium
| 부위 | 상태 | 속성 | 값 |
|---|---|---|---|
root | enabled | 높이height | 36px웹 rem — 큰 글자에서 배율대로. 앱은 최소 높이 — 글을 따라 늘어난다(label 비고) |
| 좌우 여백paddingX | spacing-x3_514pxSEED 루트 8 + 글 6 | ||
prefixIcon | enabled | 앞 아이콘size | 16px |
suffixIcon | enabled | 뒤 아이콘size | 14px |
removeButton | enabled | 지우기 버튼size | 14px누르는 영역 24 × 24 |
icon | enabled | 아이콘size | 16px |
size=large
| 부위 | 상태 | 속성 | 값 |
|---|---|---|---|
root | enabled | 높이height | 40px웹 rem — 큰 글자에서 배율대로. 앱은 최소 높이 — 글을 따라 늘어난다(label 비고) |
| 좌우 여백paddingX | spacing-x416pxSEED 루트 10 + 글 6 | ||
prefixIcon | enabled | 앞 아이콘size | 16px |
suffixIcon | enabled | 뒤 아이콘size | 16px |
removeButton | enabled | 지우기 버튼size | 16px누르는 영역 24 × 24 |
icon | enabled | 아이콘size | 16px |
size=small, layout=withText
| 부위 | 상태 | 속성 | 값 |
|---|---|---|---|
root | enabled | 최소 너비minWidth | 44px |
size=medium, layout=withText
| 부위 | 상태 | 속성 | 값 |
|---|---|---|---|
root | enabled | 최소 너비minWidth | 48px |
size=large, layout=withText
| 부위 | 상태 | 속성 | 값 |
|---|---|---|---|
root | enabled | 최소 너비minWidth | 52px |
size=small, layout=iconOnly
| 부위 | 상태 | 속성 | 값 |
|---|---|---|---|
root | enabled | 너비width | 32px |
| 좌우 여백paddingX | 0px |
size=medium, layout=iconOnly
| 부위 | 상태 | 속성 | 값 |
|---|---|---|---|
root | enabled | 너비width | 36px |
| 좌우 여백paddingX | 0px |
size=large, layout=iconOnly
| 부위 | 상태 | 속성 | 값 |
|---|---|---|---|
root | enabled | 너비width | 40px |
| 좌우 여백paddingX | 0px |
variant=solid, selected=unselected
| 부위 | 상태 | 속성 | 값 |
|---|---|---|---|
root | enabled | 배경background | bg-neutral-weak-alpha#0000000C다크 #FFFFFF20SEED 그대로 투명(검정 4.7% · 다크 흰 12.5%) — 놓인 바탕에 섞여 회색 바닥 위 1.11 · 흰 위 1.11 · 다크 1.47:1(v120) |
| 글자·아이콘foreground | fg-neutral#1A1F2E다크 #F5F6FA | ||
root | hovered | 배경background | bg-neutral-weak-alpha-pressed#00000010다크 #FFFFFF2E |
root | pressed | 배경background | bg-neutral-weak-alpha-pressed#00000010다크 #FFFFFF2E |
root | disabled | 배경background | bg-neutral-weak-alpha#0000000C다크 #FFFFFF20막혀도 바탕은 그대로 — 글 · 아이콘만 fg-disabled(공통). bg-disabled(gray-200)는 회색 바닥(bg-layer-basement, 같은 gray-200)과 1.00:1 이라 알약이 사라진다. 투명 바탕은 회색 바닥 위 1.11 · 흰 위 1.11 · 다크 1.47:1. 안 고른 칩과는 글 색으로 갈린다(SEED 도 바탕을 바꾸지 않는다 — 2026-10-17 사용자 결정 03-B 결정 1 A) |
variant=solid, selected=selected
| 부위 | 상태 | 속성 | 값 |
|---|---|---|---|
root | enabled | 배경background | bg-neutral-inverted#1A1F2E다크 #F5F6FA |
| 글자·아이콘foreground | fg-neutral-inverted#FFFFFF다크 #242938 | ||
root | hovered | 배경background | bg-neutral-inverted-pressed#535866다크 #B7BDCC |
root | pressed | 배경background | bg-neutral-inverted-pressed#535866다크 #B7BDCC |
root | disabled | 테두리borderColor | stroke-neutral-solid#767C8B다크 #838997고른 채 막힘 — 회색 채움에 짙은 1px 를 남겨 안 고른 칩과 가른다 |
| 테두리 두께borderWidth | 1px |
variant=outlineStrong
| 부위 | 상태 | 속성 | 값 |
|---|---|---|---|
root | enabled | 배경background | transparent |
| 글자·아이콘foreground | fg-neutral#1A1F2E다크 #F5F6FA | ||
| 테두리borderColor | stroke-neutral-weak#E5E8EF다크 #404757SEED stroke.neutral-muted 의 불투명 짝 — 안쪽 1px(inset) | ||
| 테두리 두께borderWidth | 1px | ||
root | hovered | 배경background | bg-layer-default-pressed#F7F8FD다크 #353B4D |
root | pressed | 배경background | bg-layer-default-pressed#F7F8FD다크 #353B4D |
root | disabled | 배경background | bg-disabled#F5F6FA다크 #353B4D |
variant=outlineStrong, selected=selected
| 부위 | 상태 | 속성 | 값 |
|---|---|---|---|
root | enabled | 배경background | bg-neutral-inverted#1A1F2E다크 #F5F6FA |
| 글자·아이콘foreground | fg-neutral-inverted#FFFFFF다크 #242938 | ||
| 테두리 두께borderWidth | 0px짙은 채움 위 테두리는 지운다(SEED Chip Tabs 와 같다) | ||
root | hovered | 배경background | bg-neutral-inverted-pressed#535866다크 #B7BDCC |
root | pressed | 배경background | bg-neutral-inverted-pressed#535866다크 #B7BDCC |
root | disabled | 배경background | bg-disabled#F5F6FA다크 #353B4D |
| 테두리borderColor | stroke-neutral-solid#767C8B다크 #838997고른 채 막힘 — 짙은 1px 로 안 고른 칩과 가른다 | ||
| 테두리 두께borderWidth | 1px |
variant=outlineWeak
| 부위 | 상태 | 속성 | 값 |
|---|---|---|---|
root | enabled | 배경background | transparent |
| 글자·아이콘foreground | fg-neutral#1A1F2E다크 #F5F6FA | ||
| 테두리borderColor | stroke-neutral-weak#E5E8EF다크 #404757SEED stroke.neutral-muted 의 불투명 짝 — 안쪽 1px(inset) | ||
| 테두리 두께borderWidth | 1px | ||
root | hovered | 배경background | bg-layer-default-pressed#F7F8FD다크 #353B4D |
root | pressed | 배경background | bg-layer-default-pressed#F7F8FD다크 #353B4D |
root | disabled | 배경background | bg-disabled#F5F6FA다크 #353B4D |
variant=outlineWeak, selected=selected
| 부위 | 상태 | 속성 | 값 |
|---|---|---|---|
root | enabled | 배경background | bg-neutral-weak#F5F6FA다크 #353B4D |
| 테두리borderColor | stroke-neutral-contrast#1A1F2E다크 #F5F6FA고름 — 짙은 1px(v113) | ||
root | hovered | 배경background | bg-neutral-weak-pressed#EDEFF3다크 #404757 |
root | pressed | 배경background | bg-neutral-weak-pressed#EDEFF3다크 #404757 |
root | disabled | 배경background | bg-disabled#F5F6FA다크 #353B4D |
| 테두리borderColor | stroke-neutral-solid#767C8B다크 #838997고른 채 막힘 — 짙은 1px 를 회색으로 남긴다 |
SEED 와 다른 점
- 반투명 색을 불투명 짝으로(v102) — Outline 테두리
stroke-neutral-weak, 누름bg-layer-default-pressed. Solid 바탕은 SEED 그대로 투명한bg-neutral-weak-alpha(누름-pressed)다 — v102 에는 검사기가 8자리 hex 를 받지 않아 불투명bg-neutral-weak로 두고 흰 표면 위에서만 썼는데, 회색 바닥 위 필터 바에서 사라져 v120 에 되돌렸다(2026-10-16 사용자 결정 — 기초 웹 01-040 B). - Outline Strong 을 고르면 테두리를 지운다 — SEED 는 짙은 채움 위에 옅은 테두리가 남는다(SEED Chip Tabs 는 지운다).
- 비활성은 흐리게 하지 않는다(v106) — SEED 는 불투명도 0.5. 막힌 Solid(안 고름)는 SEED 처럼 바탕
bg-neutral-weak-alpha를 그대로 두고, 흐림 대신 글 · 아이콘만fg-disabled다(2026-10-17 사용자 결정 — 03-B 결정 1 A). 고른 채 막힌 칩은 짙은 1pxstroke-neutral-solid로 고른 것을 남긴다(사용자 결정 2026-10-02). - 줄보다 긴 칩은 줄 폭에서 말줄임(2026-10-17 사용자 결정 — 03-E 결정 2 A) — SEED 는
white-space: nowrap만 있고 최대 폭 · 말줄임이 없다(글자를 1.5배에서 묶어 넘침이 드물다). - 큰 글자 — SEED 는 상자가 px 이고 글자를 1.5배(일부 1.35)에서 묶는다. groo 는 글자 상한을 두지 않고(03-D 결정 1), 웹은 상자도 rem 으로 커지며 앱은 최소 높이가 글을 따라 늘어난다(2026-10-17 사용자 결정 — 03-E 결정 1 C).
- 웹의 호버는 누름과 같은 바탕(v106 — SEED 도 마우스에서는 같다), 누르는 영역은 가로 · 세로 44 까지 넓힌다(SEED 에 규정 없음 — Button 과 같다).
- 입력값 칩 · 지우기 버튼 · 필터 바의 걸린 조건 모습을 정했다 — SEED 는 "Suffix 에 Remove 버튼", "Filter Bar 템플릿" 이라고만 하고 치수 · 모양이 없다.
- 아이콘은 lucide 선 아이콘(v106) — 여는 칩
chevron-down, 지우기x, 필터 지우기rotate-ccw.
Migration notes
2026-10-17 — 큰 글자 · 줄보다 긴 칩 · Home · End · 막힌 Solid(03-E · 03-B 사용자 결정)
구현 조사에서 사용자가 정했다(비교 페이지 03-E https://claude.ai/artifact/FKYaqu7zAR5T2HVwFnx5oD · 03-B https://claude.ai/artifact/SZwwW7UK1FxtZynvYBFLLx). 옛 스펙은 chip.history/v-pre-03e-03b.*.
- 큰 글자(03-E 결정 1 C) — 웹은 그대로(rem). 앱
PChip은 높이를 최소 높이로 — 지금minHeight: m.height, maxHeight: m.height(p_chip.dart:214-217)라 200% 에서 글 38 이 36 상자를 넘는다. 최대 높이를 걷고 위아래 (높이 − 19) ÷ 2 를 둔다. - 줄보다 긴 칩(03-E 결정 2 A · 후속) —
root.maxWidth100% ·label.overflow말줄임. 줄바꿈 묶음 · 가로 스크롤 줄 · Chip Tabs 모두(스크롤 줄은 보이는 줄 폭). 웹은 칩이 줄 밖으로 나가 화면이 옆으로 밀리고, 앱은 글이 칩 윤곽 밖으로 넘쳐 지우기 × 가 잘린다(200% · 360 에서 131px). 칩 최대 폭 = 줄 폭, 글만 줄고 아이콘 · 지우기는 남게. 레시피 · 예제는 아직 그리지 않았다 — 칩 글을 따로 감싸는 칸이 입력값 칩에만 있다. - Home · End(03-E 결정 3 A) — 웹 공용 라디오 묶음(Chip 하나 고르기 · Radio Group · Segmented Control · Select Box 하나 고르기 · List 라디오)은 Radix RovingFocusGroup 이 Home · End 로 초점만 옮겨 초점과 고른 것이 갈렸다. 레시피는 묶음에서 라디오의 Home · End · PageUp · PageDown 을 막는다(
ignoreRadioJumpKeys— radio-group.tsx). 앱은 바뀌는 것 없음. - 막힌 Solid(03-B 결정 1 A) — 레시피 · 예제 · 미리보기의 Solid 안 고름 막힘 바탕을
bg-disabled→bg-neutral-weak-alpha로. 웹 · 앱 ds 의 Chip 도 같게(지금 웹chip-variants.ts는 v120 전이라 안 고른 칩도bg-neutral-weak).
2026-10-02 — 새로 둔다(SEED Chip)
사용자가 비교 페이지에서 여덟 가지를 모두 SEED 로 정했다 — 칩이 맡는 일 넷(고르기 · 제안 · 필터 바 · 입력값) · 32 · 36 · 40 기본 36 · 고른 색 중립 · 변형 셋 · 하나 고르기는 라디오("전체" 맨 앞) · 필터 바(조건마다 칩, 걸린 조건은 짙은 채움 + 값 요약, 맨 앞 지우기) · 3상태를 걷고 "고른 것만 · 고른 것 빼고" · 제안 칩은 고른 표시 없음. 고른 채 막힌 칩은 짙은 1px 를 남긴다. 옛 DESIGN.md 의 Tag / Chip(v73)을 대신한다.
제품은 앱 적용 단계에서 옮긴다(2026-10-01 조사 — 세 제품 코드를 읽고 Desk 웹 · HR 은 크로미움에 띄워 쟀다).
- Desk 웹 — 공용 Chip 2곳 · 칩 모양 탭 12 · 폼 값 탭 트랙 15 · ToggleGroup 9 · 손으로 만든 칩 18종. 높이 11가지(28 ~ 46) · 모서리 4 · 8 · 16 · full · 글자 12 ~ 14, 고른 표시 8가지. 다크에서 브랜드 채움이 바탕과 1.73 ~ 1.96:1, ToggleGroup 고름 1.12:1. 폼 값 · 필터 27곳이 탭으로 읽힌다(화살표마다 언어가 바뀌고 이메일 주기가 저장된다). 친구 추가 칩이 토글로 읽히고, 지우기 × 이름이 모두 "초기화"(14 · 17). 가계부 "전체 · 지출 · 수입" 칩은 필터 대화상자를 걸면 효과가 없어지는데 고른 표시는 남는다.
- Desk 앱 — PChip 10 · PTypeChip 2 · PToggle 3 · PCategoryTile 4 · 화면 전용 칩 13종 · PTabs 37. 높이 28 ~ 43.5 · 글자 13.5(토큰 밖) · 고른 표시 11가지. PChip 은 누르거나 포커스해도 표시가 없고, 켜지면 크기가 변하는 칩이 둘이다. 거래 종류 둘 다 끄면 엉뚱한 "수입" 칩이 뜬다(D1). 기관 칩 글자 70곳 중 12곳이 4.5:1 미만(최저 2.42). 요일 켬 · 끔 1.02:1. 3상태 필터의 "빼고" 4.00:1. 키보드로 못 닿는 칩 9종.
- HR 웹 — 칩이 없다. 2 ~ 4개 폼 값 16칸이 모두 Select(→ Chip), 예 / 아니오 3칸(→ Checkbox), 칩처럼 생긴 Badge 49 + 알약 4 는 누를 수 없다. 업무 보고 필터 개수가 늘 2(초기화가 비활성이 안 됨), 캘린더 필터는 전체에서 하나를 누르면 그것만 남는다.