BadgeToggle
필 버튼 단일 선택 그룹 — APG radio group 패턴(roving tabindex + 화살표 이동 + 즉시 선택). 필터 칩 줄에 적합하고 비활성 항목은 건너뜁니다. 비제어(defaultValue) 우선 (DK 사양 승격).
마지막 업데이트 2026-06-11
한눈에#
필 형태로 하나만 켜는 단일 선택 필터 그룹입니다 — RadioGroup과 같은 APG 패턴이지만 시각은 둥근 필(pill)이라 필터 칩 줄에 어울립니다.
- APG radio group
- 필 단일 선택
- showAll '전체' 항목
- 44px 히트 영역
Tab으로 그룹 진입, 화살표로 순환 이동하며 즉시 선택 — 비활성 항목은 건너뜁니다
사용 시점#
필 줄에서 하나만 켜는 단일 선택 필터면 BadgeToggle — 다중 선택이나 다른 인터랙션 칩은 다른 컴포넌트입니다.
상태·기간 필터처럼 '전체' 포함 가로 필 줄에서 하나만 켜는 단일 선택
플레이그라운드#
컨트롤로 props를 조작하면 미리보기와 코드가 실시간 갱신됩니다.
import { BadgeToggle } from '@wds/ui-web';
<BadgeToggle
aria-label="상태 필터"
options={[
{ value: 'active', label: '활성' },
{ value: 'pending', label: '대기' },
{ value: 'done', label: '완료' },
]}
/>변형#
showAll이면 value=''인 "전체" 항목이 맨 앞에 합성되고, defaultValue가
없을 때 전체가 초기 선택됩니다. allLabel로 라벨을 바꿀 수 있습니다.
크기#
단일 크기입니다 — 시각 32px 필(space.8)에 radius.full이고, 히트 영역은
모든 방향으로 확장돼 44px 터치 타깃을 채웁니다. 라벨이 길어도 줄바꿈 없이
가로로 늘어나며, 그룹은 폭이 부족하면 다음 줄로 래핑됩니다.
상태#
- Default —
color.surface-muted배경 +color.text-muted잉크 - Hover (미선택) —
color.surface-hover배경 +color.text - Focus —
:focus-visible에color.focus-ring2px 아웃라인 - 선택(aria-checked) —
color.primary-subtle배경 +color.primary보더 +color.primary-text잉크 - Disabled —
color.disabled-bg/color.disabled-fg+ 커서 차단
Props#
| Prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
options | ReadonlyArray<BadgeToggleOption> | — | 항목 배열 (아래 표) — 데이터 prop 방식 |
defaultValue | string | — | 초기 선택 value — 이후 상태는 내부 소유(비제어) |
onChange | (value: string) => void | — | 선택 변경 콜백 — 같은 값 재선택은 발화하지 않음 (showAll의 전체는 value="") |
showAll | boolean | false | 맨 앞에 '전체'(value='') 항목 합성 — defaultValue 없으면 전체가 초기 선택 |
allLabel | string | '전체' | showAll 항목의 라벨 |
aria-label | string | — | 필터 그룹의 접근성 이름 — radiogroup 계약상 필수 |
…rest | Omit<HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'> | — | className 등은 그룹 div(role=radiogroup)로 전달 |
BadgeToggleOption:
| Prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
value | string | — | 고유 value — 선택 식별자 |
label | string | — | 필 버튼에 표시되는 라벨 |
disabled | boolean | false | 선택 차단 — 키보드 이동에서도 건너뜀 |
접근성#
그룹이 role="radiogroup"(이름은 aria-label 필수), 각 항목이
button[role="radio"] + aria-checked입니다. roving tabindex로 선택된
항목(없으면 첫 활성 항목)만 tabIndex=0이 되어 그룹 진입 후 화살표로 이동합니다.
| 키 | 동작 |
|---|---|
Tab | 그룹 진입 — 선택(없으면 첫 활성) 항목에 포커스 |
→ / ↓ | 다음 활성 항목으로 이동 + 즉시 선택 (순환, 비활성 건너뜀) |
← / ↑ | 이전 활성 항목으로 이동 + 즉시 선택 (순환, 비활성 건너뜀) |
Space / Enter | 포커스 항목 선택 (네이티브 button 클릭) |
비활성 항목은 네이티브 disabled로 포커스·선택·키보드 이동에서 모두 제외됩니다.
토큰#
component 토큰 없이 semantic을 직접 소비합니다(신설 기준 §4 미충족).
| 속성 | 토큰 |
|---|---|
| 필 기본 | color.surface-muted · color.text-muted · radius.full · 높이 space.8 |
| Hover(미선택) | color.surface-hover · color.text |
눌림(:active, 미선택) | color.surface-pressed |
| Focus | color.focus-ring(2px 아웃라인) |
| 선택 | color.primary-subtle · color.primary(보더) · color.primary-text |
| Disabled | color.disabled-bg · color.disabled-fg |
| 모션 | duration.fast + ease.standard |