본문으로 건너뛰기
액션 / toggle-group

ToggleGroup

눌림 상태 버튼 묶음 — 다중 토글 또는 해제 가능한 단일 선택.
액션toggle-groupInteractivetoggle group토글 그룹multiplesingle
01 · Specimen

먼저 보고, 그다음 계약을 읽습니다

눌림 상태 버튼 묶음 — 다중 토글 또는 해제 가능한 단일 선택.

Workbench 불러오는 중…
Component intent의도와 경계 읽기

정렬/서식 툴바·필터 칩처럼 "0개 또는 N개"가 자연스러운 곳을 위한 버튼 묶음. type="multiple" 은 다중 토글(체크박스 의미, value: T[]), type="single" 은 **해제 가능한** 단일 선택(같은 항목 재클릭 시 null)이다. 항상 하나가 선택되는 단일 필수 선택이면 Seg 를, 낱개 토글이면 Toggle 을 쓴다. 외부 dep 0 — 네이티브 <button aria-pressed> 묶음이며 스타일은 100% CSS 클래스(.axe-toggle-group)로 처리한다. controlled 전용이고 value 는 제네릭 T(string 서브타입)로 좁혀진다.

02 · Use

예제

SSOT에 등록된 실제 API 기준 snippet입니다. standalone 배지만 독립 실행 단위이며, fragment는 주변 state·handler 문맥을 생략합니다.

01다중 토글 (서식 툴바)tsxfragment
다중 토글 (서식 툴바)
import { ToggleGroup } from "@axe/ui";import { useState } from "react";function FormatToolbar() {  const [fmt, setFmt] = useState<string[]>([]);  return (    <ToggleGroup      type="multiple"      ariaLabel="텍스트 서식"      value={fmt}      onValueChange={setFmt}      options={[        { value: "bold", label: "B" },        { value: "italic", label: "I" },        { value: "underline", label: "U" },      ]}    />  );}
02해제 가능한 단일 (정렬)tsxfragment
해제 가능한 단일 (정렬)
import { ToggleGroup } from "@axe/ui";import { useState } from "react";function AlignPicker() {  const [align, setAlign] = useState<string | null>(null);  return (    <ToggleGroup      type="single"      ariaLabel="정렬"      value={align}      onValueChange={setAlign}      options={[        { value: "left", label: "왼쪽" },        { value: "center", label: "가운데" },        { value: "right", label: "오른쪽" },      ]}    />  );}
03CSS-only (비-React)htmlfragment
CSS-only (비-React)
<div class="axe-toggle-group" role="group" aria-label="텍스트 서식">  <button type="button" class="axe-toggle-group__btn" aria-pressed="true">B</button>  <button type="button" class="axe-toggle-group__btn" aria-pressed="false">I</button></div>
03 · React

Props

TSX 소스가 진실입니다. 주요 export 컴포넌트의 public API만 노출합니다.

이름타입필수기본값설명
type"multiple" | "single"필수다중 토글(체크박스 의미) 또는 해제 가능한 단일 선택(같은 항목 재클릭 시 null). value/onValueChange 타입을 판별.
valueT[] (multiple) | T | null (single)필수눌린 값(들) (controlled). multiple=값 배열, single=값 또는 해제 시 null.
onValueChange(value: T[]) => void (multiple) | (value: T | null) => void (single)필수값 변경 콜백. type 에 대응하는 다음 값을 넘김.
optionsToggleGroupOption<T>[]필수버튼 항목 목록. 각 항목 = { value: T; label: React.ReactNode; disabled?: boolean }.
ariaLabelstring필수role="group" 컨테이너의 접근성 라벨.
size"sm" | "md""md"버튼 크기.
disabledbooleanfalse묶음 전체 비활성화 (개별은 option.disabled).
...restOmit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'>className 등 나머지는 루트 <div role="group"> 으로 전파.
04 · Any stack

.axe-* 클래스 계약

React 밖에서도 같은 표면을 그리는 공개 계약입니다. stable은 minor 버전 안에서 이름을 바꾸지 않습니다.

클래스안정성용도
.axe-toggle-groupstable묶음 루트 컨테이너 (role="group", pill 트랙).
.axe-toggle-group__btnstable묶음 내부 각 토글 버튼.
.axe-toggle-group--smstablesm 크기 변형 (버튼 높이 24px).
비-React 소비 노트
눌림은 각 버튼의 aria-pressed 속성으로 표현 — 서버렌더는 이 속성만 토글하면 동일 모양. 참고: 컴포넌트가 전체 비활성 시 붙이는 axe-toggle-group--disabled 클래스에는 대응 CSS 규칙이 없어(현재 no-op) 시각은 버튼 disabled 속성이 담당한다.
05 · Inclusive

접근성

키보드, ARIA, 구현 노트를 함께 검토합니다.

Keyboard
  • Tab 으로 버튼 순회 (roving tabindex 없이 각 버튼이 tab stop)
  • Enter/Space 로 해당 항목 토글
ARIA

컨테이너 role="group" + aria-label(ariaLabel). 각 버튼은 aria-pressed 로 눌림 표시 — multiple 은 여러 개가 동시에 true, single 은 최대 1개 true(재클릭 시 전부 false).

Notes

개별 비활성 = option.disabled → 해당 <button> 의 disabled 속성. 전체 비활성 = 모든 버튼 disabled(시각은 버튼 :disabled 규칙이 담당). 라디오 의미가 아니므로 role 은 radiogroup 이 아닌 group 이다.

06 · Judgment

권장 · 지양

권장
  • 필터/서식처럼 0~N개가 자연스러운 곳에 쓸 것.
  • ariaLabel 로 이 묶음이 무엇을 제어하는지 명시할 것.
지양
  • 항상 하나가 선택돼야 하는 필수 단일 선택엔 ToggleGroup 대신 Seg 를 쓸 것.
  • 낱개 on/off 하나엔 Toggle 을 쓸 것.
검색창을 열면 컴포넌트 인덱스를 불러옵니다.