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.

PropTypeDefaultDescription
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.
defaultValuestring | string[]The pressed value(s) for an uncontrolled group. Use a string for single, an array for multiple.
valuestring | string[]The pressed value(s) for a controlled group. Pair with onValueChange.
onValueChange(value: string | string[]) => voidCalled 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.
rovingFocusbooleantrueWhether the group is a single tab stop with arrow-key navigation inside it.
loopbooleantrueWhether arrow keys wrap from the last item back to the first.
disabledbooleanfalseDisables the entire group.
classNamestringMerged onto the group root, which defaults to w-fit.
...restRadix ToggleGroup.Root propsEverything else is forwarded to the root div.

ToggleGroupItem — one toggleable item.

PropTypeDefaultDescription
valuerequiredstringUnique 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.
disabledbooleanfalseDisables this single item.
classNamestringAdditional Tailwind classes to merge onto the item.
...restRadix ToggleGroup.Item propsEverything 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 single mode each item is announced as role="radio" with aria-checked; in multiple mode items keep the toggle semantics and report aria-pressed.
  • Icon-only items have no visible text — always pass an aria-label describing the action.
  • Each item renders a focus-visible ring on keyboard navigation and respects the disabled attribute, 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-variant and data-size you 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.