Toggle Group
Segmented control for switching between related options. Supports single and multiple selection, three variants and sizes, icon-only buttons, vertical layout, and full keyboard navigation with roving tabindex — following the WAI-ARIA radiogroup and group patterns.
Live Preview
Interact with the ToggleGroup component in real time. Switch modes, sizes, and variants to see the segmented row adapt.
<ToggleGroup
ariaLabel="Text alignment"
mode="single"
size="md"
variant="default"
options={alignmentOptions}
value={"center"}
onChange={setValue}
/>Installation
Install the Aidash Components package using your preferred package manager.
$ pnpm add @aidash/componentsImport
Import the ToggleGroup component into your file.
import { ToggleGroup } from '@/components/aidash/toggle-group';Basic Usage
Single-selection segmented control with three text-only options.
const [range, setRange] = useState('week');
<ToggleGroup
ariaLabel="Date range"
mode="single"
options={[
{ value: 'day', label: 'Day' },
{ value: 'week', label: 'Week' },
{ value: 'month', label: 'Month' },
]}
value={range}
onChange={(v) => setRange(v as string)}
/>Multiple Selection
Set mode="multiple" to let users select any number of options. Icon-only buttons must provide ariaLabel.
1const [formatting, setFormatting] = useState<string[]>(['bold']);2 3<ToggleGroup4 ariaLabel="Text formatting"5 mode="multiple"6 options={[7 { value: 'bold', icon: TextBoldIcon, ariaLabel: 'Bold' },8 { value: 'italic', icon: TextItalicIcon, ariaLabel: 'Italic' },9 { value: 'underline', icon: TextUnderlineIcon, ariaLabel: 'Underline' },10 ]}11 value={formatting}12 onChange={(v) => setFormatting(v as string[])}13/>Variants
Three visual styles. Default uses a subtle inset pill; outline shares a bordered container; ghost has no chrome and only shows the active tint.
1<ToggleGroup variant="default" options={alignmentOptions} ... />2<ToggleGroup variant="outline" options={alignmentOptions} ... />3<ToggleGroup variant="ghost" options={alignmentOptions} ... />Sizes
Three sizes to fit different layout contexts.
1<ToggleGroup size="sm" options={alignmentOptions} value="left" />2<ToggleGroup size="md" options={alignmentOptions} value="center" />3<ToggleGroup size="lg" options={alignmentOptions} value="right" />Vertical Orientation
Stack the buttons vertically. Arrow-key navigation follows the axis (Up/Down).
1<ToggleGroup2 ariaLabel="View"3 orientation="vertical"4 options={[5 { value: 'board', label: 'Board' },6 { value: 'list', label: 'List' },7 { value: 'calendar', label: 'Calendar' },8 ]}9 value={view}10 onChange={(v) => setView(v as string)}11/>Disabled State
Disable the whole group with the disabled prop, or disable individual options via option.disabled.
1<ToggleGroup disabled options={alignmentOptions} value="center" />2 3<ToggleGroup4 options={[5 { value: 'left', label: 'Left', icon: AlignLeftIcon },6 { value: 'center', label: 'Center', icon: AlignCenterIcon },7 { value: 'right', label: 'Right', icon: AlignRightIcon, disabled: true },8 { value: 'justify', label: 'Justify', icon: TextAlignJustifyCenterIcon },9 ]}10 value="center"11/>Accessibility
Follows the WAI-ARIA radiogroup pattern in single mode and the group pattern in multiple mode.
role="radiogroup" vs role="group"
Single mode renders the root as role="radiogroup"; multiple mode uses role="group". An ariaLabel is required to name the group.
aria-checked / aria-pressed
In single mode each button carries role="radio" + aria-checked; in multiple mode toggles expose aria-pressed.
Keyboard Navigation
Arrow keys (Left/Right for horizontal, Up/Down for vertical) move focus between non-disabled options; in single mode arrow keys also select. Home / End jump to the first / last non-disabled option. Space and Enter toggle in multiple mode.
Roving Tabindex
Only the currently selected (or first non-disabled) option is in the tab order (tabIndex=0); the rest use -1, so a single Tab press moves in and out of the whole group.
1{/* Single mode → renders <div role="radiogroup"> with role="radio" children */}2<ToggleGroup3 ariaLabel="Text alignment"4 mode="single"5 options={alignmentOptions}6 value={alignment}7 onChange={(v) => setAlignment(v as string)}8/>9 10{/* Multiple mode → renders <div role="group"> with aria-pressed buttons */}11<ToggleGroup12 ariaLabel="Text formatting"13 mode="multiple"14 options={formattingOptions}15 value={formatting}16 onChange={(v) => setFormatting(v as string[])}17/>API Reference
Complete list of props for the ToggleGroup component.
| Prop | Type | Default | Description |
|---|---|---|---|
| options* | ToggleGroupOption[] | — | Array of options to render as toggle buttons. |
| value | string | string[] | — | Selected value. String in single mode, string[] in multiple mode. |
| onChange | (value: string | string[]) => void | — | Fires when selection changes. Shape mirrors value. |
| mode | 'single' | 'multiple' | 'single' | Whether only one or many options can be selected at the same time. |
| size | 'sm' | 'md' | 'lg' | 'md' | Size preset for the segmented row. |
| variant | 'default' | 'outline' | 'ghost' | 'default' | Visual style of the container and active state. |
| orientation | 'horizontal' | 'vertical' | 'horizontal' | Layout direction; also flips the arrow-key axis. |
| disabled | boolean | false | Disable the entire group. |
| allowDeselect | boolean | false | In single mode, allow clicking the selected option again to clear it. |
| ariaLabel* | string | — | Accessible label for the group (radiogroup / group). |
| className | string | '' | Additional classes appended to the root container. |
value and onChange types depend on mode: single mode uses a plain string, while multiple mode uses string[]. Narrow the type at the call site (e.g. v as string[]) when reading the callback value.Related
Other components that work well alongside Toggle Group.