A React toggle group with Liquid Glass selected states, single or multiple selection, and two orientations.
ToggleGroup groups related toggle buttons on one glass surface. Use it for view switchers and formatting controls with single or multiple selection.
The view switcher below uses the real Toggle Group. The pressed item receives the glass selected state and updates the text underneath.
Options are passed through the items array; each item's value maps to the group value.
Give the group an accessible name with aria-label or aria-labelledby. Items that render only an icon need their own aria-label.
Current view: Grid
Supports xs / sm / md / lg / xl, defaulting to md.
Use multiple to allow more than one pressed item; the default is single selection.
Use orientation="vertical" for a vertical group:
value and onValueChange let external state fully control the selection. The example below stays controlled after clearing:
Set disabled on the group to disable every item, or on a single item to disable only that option.
ToggleGroup renders a group whose items are toggle buttons with aria-pressed. Name the group with aria-label or aria-labelledby; icon-only items need their own name.
Arrow keys move focus within the group, Home and End jump to the ends, and Space or Enter toggles the focused item. In single-selection mode, the group value is the single source of truth; control it when the selection must not be cleared. See the accessibility guide for keyboard details.
ToggleGroup
| Prop | Type | Default | Description |
|---|---|---|---|
value | readonly string[] | — | Controlled pressed values. |
defaultValue | readonly string[] | [] | Initial pressed values when uncontrolled. |
onValueChange | (value: string[], details) => void | — | Called when the pressed values change. |
multiple | boolean | false | Allows multiple pressed items. |
orientation | "horizontal" | "vertical" | "horizontal" | Layout and keyboard orientation. |
loopFocus | boolean | true | Loops keyboard focus back to the first item after the last one. |
disabled | boolean | false | Disables every item. |
size | "xs" | "sm" | "md" | "lg" | "xl" | "md" | Controls item height, padding, text, and icons. |
items | readonly ToggleGroupItemProps[] | — | Options rendered by the group. |
aria-label | string | — | Accessible name for the group. |
aria-labelledby | string | — | Names the group from another element. |
render | ReactElement | ((props, state) => ReactElement) | — | Replaces the group element. |
ref | Ref<HTMLDivElement> | — | Ref forwarded to the group element. |
className | string | — | Tailwind classes merged into the group root. |
style | CSSProperties | — | Inline styles merged into the same element as className. |
ui | { root?: ClassValue; glass?: ClassValue; rim?: ClassValue; item?: ClassValue; content?: ClassValue; icon?: ClassValue; label?: ClassValue } | — | Tailwind classes for internal slots, keyed by data-slot. |
ToggleGroupItemProps
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Required value used by the group. |
label | ReactNode | — | Visible content inside the item. |
icon | ReactNode | — | Decorative icon rendered before the label. |
onPressedChange | (pressed, details) => void | — | Called when this item's pressed state changes. |
disabled | boolean | false | Disables the item. |
aria-label | string | — | Accessible name for icon-only items. |
aria-labelledby | string | — | Names an icon-only item from another element. |
nativeButton | boolean | true | Whether the item renders a native <button>. |
render | ReactElement | ((props, state) => ReactElement) | — | Replaces the item element. |
ref | Ref<HTMLButtonElement> | — | Ref forwarded to the item element. |
className | string | — | Tailwind classes merged into the item root. |
style | CSSProperties | — | Inline styles merged into the same element as className. |
ui | { item?: ClassValue; content?: ClassValue; icon?: ClassValue; label?: ClassValue } | — | Tailwind classes for this item's internal slots, keyed by data-slot. |
Items do not accept pressed or defaultPressed; the group value / defaultValue is the single source of truth for selection. Root ui is merged into every item first, then the item's ui, then the item's className.
| Attribute | Description |
|---|---|
data-disabled | Present when the group or an item is disabled. |
data-orientation | Indicates the orientation (horizontal or vertical). |
data-multiple | Present when the group allows multiple pressed items. |
data-pressed | Present on a pressed item. |
data-slot | Marks internal parts (root, glass, rim, item, content, icon, label). |
The component uses the shared glass material. Tune shared --ui-glass-* tokens on a parent, use className for layout, and use ui for internal slots keyed by data-slot. Component-specific values live in src/theme/toggle-group.ts. See the theming guide for token layers and presets.