Tag
칩/태그 — variant 5종 × size 2단. onRemove를 주면 히트 영역이 확장된 제거 버튼이 붙는 입력성 칩이 됩니다.
마지막 업데이트 2026-06-22
한눈에#
적용된 필터·선택 항목처럼 사용자가 다루는 값을 표시하는 칩입니다 — onRemove를 주면 제거 가능한 입력성 칩이 됩니다.
- 의미 5종 × 2 크기
- onRemove 입력성 칩
- 제거 히트 확장
- 긴 라벨 말줄임
제거 버튼은 시각은 작아도 ::after로 히트 영역이 확장됩니다(버튼 박스 20px → 44px)
사용 시점#
사용자가 다루는 값(필터·선택 항목)을 라벨로 보여주면 Tag — 상호작용 칩이나 읽기 전용 표식은 다른 컴포넌트입니다.
권장 — 이렇게 쓰세요
지양 — 이러지 마세요
쓴다 — 적용된 필터·선택 항목처럼 사용자가 다루는 값(onRemove로 제거 가능한 입력성 칩)
대신 Chip — 클릭으로 토글·실행되는 인터랙션 칩(assist/filter/input/suggestion)
대신 Badge — 수량·상태처럼 사용자가 다루지 않는 읽기 전용 표식
플레이그라운드#
컨트롤로 props를 조작하면 미리보기와 코드가 실시간 갱신됩니다.
Tag를 직접 조작해 보세요
속성·테마·토큰을 바꾸고 React·Flutter 코드를 확인하는 풀스크린 빌더로 엽니다.
플레이그라운드는 넓은 작업 영역이 필요해 웹·태블릿에서 편집할 수 있어요.
해부#
알약 위에 토큰 실측을 핀으로 얹습니다 — 값이 바뀌면 핀도 함께 움직입니다(드리프트 0).
- padding-inline
- 12px
space-3 - padding-block
- 4px
space-1 - gap
- 4px
space-1 - radius
- full
radius-full - font
- 14 / 500
body-2 - remove hit
- 44px (::after)
알약은 radius.full로 콘텐츠 높이에 맞춰 둥글어집니다 — 명시 높이 토큰 없이 패딩과 폰트가 높이를 결정합니다. 제거 버튼은 버튼 박스 20px(icon.size-md, 글리프 16px)이고 히트 영역은 ::after로 44px까지 확장됩니다.
변형#
5단 의미 색. 색은 이름이 아니라 실제 스와치와 측정된 대비로 확인하세요 — 상태색은 base 색의 8% color-mix 틴트 위에 *-text 잉크로 AA 4.5:1을 보장합니다.
- bg
surface-muted- fg
text-muted
- bg
primary-subtle- fg
primary-text
- bg
success 8%- fg
success-text
- bg
warning 8%- fg
warning-text
- bg
error 8%- fg
error-text
틴트는 8% 고정입니다 — 12%는 success-text와 4.39:1로 AA 미달(선례 실측). 대비 배지는 라이트 테마 기준이며, 다크 테마에서도 다섯 변형 모두 AA(4.5:1 이상)를 보장합니다.
크기#
size로 2단 — sm(caption 폰트)·md(body-2 폰트). 두 크기 모두 알약 형태와 제거 버튼 히트 영역을 공유하고, 인라인 패딩만 달라집니다.
상태#
onRemove를 제공하면 제거 버튼(CloseIcon)이 렌더됩니다. 함수 prop은
서버 MDX로 전달할 수 없어 코드로 보입니다:
'use client';
function FilterTags({ filters, onRemove }: FilterTagsProps) {
return filters.map((filter) => (
<Tag key={filter} variant="primary" onRemove={() => onRemove(filter)}>
{filter}
</Tag>
));
}
- 제거 버튼은 기본 70% 투명도, hover 시 100% — 라벨보다 조용하게 유지됩니다
- 긴 라벨은 말줄임(ellipsis) 처리됩니다 (
max-width: 100%)
Props#
| Prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
variant | 'neutral' | 'primary' | 'success' | 'warning' | 'error' | neutral | 의미 색 — *-text 잉크 + 8% 틴트(neutral은 surface-muted) |
size | 'sm' | 'md' | md | sm은 caption, md는 body-2 폰트 |
onRemove | () => void | — | 제공 시 제거 버튼을 렌더하고 클릭 시 호출 |
removeLabel | string | 제거 | 제거 버튼 aria-label (기본 '제거') |
ref | Ref<HTMLSpanElement> | — | 루트 <span>으로 전달되는 ref (React 19 ref-as-prop) |
접근성#
- 제거 버튼은 네이티브
<button>+aria-label(기본 ‘제거’) — 라벨이 여러 개일 때는removeLabel="React 태그 제거"처럼 대상을 명시하세요 - 제거 버튼은 시각은 작지만
::after로 히트 영역이 44px까지 확장됩니다(버튼 박스 20px → 44px) :focus-visible2pxfocus-ring링, 아이콘은 장식(aria-hidden처리된 CloseIcon)- 잉크는
*-text토큰 — AA 대비 빌드 게이트 보장
토큰#
component 토큰 없이 semantic을 직접 소비합니다(신설 기준 §4 미충족).
| 속성 | 토큰 |
|---|---|
| neutral | color.surface-muted + color.text-muted |
| primary | color.primary-subtle + color.primary-text |
| success/warning/error | base 색 8% color-mix 틴트 + color.*-text |
| 형태 | radius.full · space.1/2/3 |
| 타이포 | font-size.caption(sm) / font-size.body-2(md) + font-weight.medium |
| 제거 버튼 | icon.size-sm/md · 눌림 color.surface-pressed · duration.fast + ease.standard |