Components
Toggle Group
A set of two-state buttons that can be toggled on or off, grouped into a single segmented control for mutually exclusive or multi-select choices.
Basic usage
With type="single" only one item can be pressed at a time — ideal for choices like text alignment.
Multiple selection
Switch to type="multiple" to let several items stay pressed at once, like a text-formatting toolbar.
Variant
The outline variant adds a shared border, reading as a distinct segmented control. Neighbouring items drop their left border so the seams stay single-width, and only the first and last corners are rounded.
Sizes
Three sizes — sm, the default, and lg — set on the group and passed to every item through context. An item's own size or variant only takes effect when the group leaves that prop unset.
Full-width segments
Items are flex children that grow, so overriding the root's default w-fit with a width of your own turns the group into an evenly divided segmented control — the shape a range picker or a view switcher usually wants.
Props
ToggleGroup — the root container.
| Prop | Type | Default | Description |
|---|---|---|---|
typerequired | 'single' | 'multiple' | — | Whether one item or several items can be pressed at once. |
variant | 'default' | 'outline' | 'default' | Visual style handed down to every item through context. |
size | 'default' | 'sm' | 'lg' | 'default' | Height and padding handed down to every item — 36px, 32px and 40px respectively. |
defaultValue | string | string[] | — | The pressed value(s) for an uncontrolled group. Use a string for single, an array for multiple. |
value | string | string[] | — | The pressed value(s) for a controlled group. Pair with onValueChange. |
onValueChange | (value: string | string[]) => void | — | Called when the pressed value(s) change. The argument follows type — a string for single, an array for multiple. |
orientation | 'horizontal' | 'vertical' | — | Arrow-key direction for roving focus. The root lays items out in a row either way — add your own flex classes for a column. |
rovingFocus | boolean | true | Whether the group is a single tab stop with arrow-key navigation inside it. |
loop | boolean | true | Whether arrow keys wrap from the last item back to the first. |
disabled | boolean | false | Disables the entire group. |
className | string | — | Merged onto the group root, which defaults to w-fit. |
...rest | Radix ToggleGroup.Root props | — | Everything else is forwarded to the root div. |
ToggleGroupItem — one toggleable item.
| Prop | Type | Default | Description |
|---|---|---|---|
valuerequired | string | — | Unique value that identifies the item within the group. |
variant | 'default' | 'outline' | — | Per-item style. Only applies when the group leaves variant unset — the group value wins. |
size | 'default' | 'sm' | 'lg' | — | Per-item size. Only applies when the group leaves size unset — the group value wins. |
disabled | boolean | false | Disables this single item. |
className | string | — | Additional Tailwind classes to merge onto the item. |
...rest | Radix ToggleGroup.Item props | — | Everything else is forwarded to the underlying button. |
Items are styled with the same exported toggleVariants recipe that Toggle uses, so the two components always agree on height, padding and pressed styling.
Accessibility
- Built on Radix Toggle Group — the root exposes
role="group"and arrow keys move focus between items as a single tab stop (roving tabindex). - In
singlemode each item is announced asrole="radio"witharia-checked; inmultiplemode items keep the toggle semantics and reportaria-pressed. - Icon-only items have no visible text — always pass an
aria-labeldescribing the action. - Each item renders a focus-visible ring on keyboard navigation and respects the
disabledattribute, removing it from the tab order. The focused item is raised above its neighbours so the ring is never clipped by the adjoining segment. - The root and every item mirror the
data-variantanddata-sizeyou actually set — the item resolving the group's value first, and both attributes absent while you stay on the defaults. That is what the seam and shadow rules key off, and a convenient hook for your own styling or tests.