Toggle Group
Shared state for a series of Toggles. Renders a
<div role="group">, makes the whole set one tab stop, and owns the list of
pressed values.
Like a radio group this is a keyboard mode as well as a state container. Unlike
a radio group, moving does not select: arrowing past a toggle leaves it
untouched, and Space or Enter is what presses it. That makes a toggle group safe
for choices a RadioGroup is not, including ones that fire
a request.
Import
import { Toggle, ToggleGroup } from "@forte-ui/react";Every toggle in a group needs a value. The group's value is the list of
pressed toggles' values, so one without a value can never appear in it — Base
UI logs an error in development when that happens.
Examples
Multiple
multiple lets any number of toggles be pressed at once. This is Base UI's own
example, styled with our tokens.
Without it, pressing one unpresses the rest. Note what that still is not: a radio group. Pressing the pressed toggle turns it off, so an empty selection stays reachable either way — which is exactly why a toggle group is the wrong control for a required choice.
Rendering at balanced quality.
Segmented
segmented puts one padded panel behind the whole set. It is deliberately the
same surface, padding and radius that Tabs uses for its
pill variant, so a segmented group and a pill tab strip on the same screen
read as the same kind of object. Pair it with variant="solid" for the classic
filled segmented control, and fullWidth to split the container equally between
the toggles.
Use segmented when the toggles are alternatives — one strip, one decision.
Leave it off when they are neighbours in a toolbar, like the alignment and
formatting groups above.
Shared appearance
variant, tone and size set on the group become the default for every
toggle inside it, so a strip stays uniform without repeating three props per
item. A toggle's own prop still wins.
This is React context rather than CSS inheritance, and it has to be. The
appearance knobs are declared on each toggle's own root rule — that placement is
what lets you re-skin a single toggle, because an element's own declaration
beats an inherited one — so a value set on the group would be inherited and then
immediately overwritten. The data-* attributes the rules key off are resolved
in JavaScript and written onto each toggle.
Orientation
orientation="vertical" stacks the toggles and moves the arrow keys onto the
block axis.
Controlled
Pass value and onValueChange for a controlled group; defaultValue for an
uncontrolled one. The callback receives the new array first and Base UI's event
details second.
Showing: status, updated.
Disabled
disabled on the group reaches every toggle inside it.
Accessibility
| Key | Behaviour |
|---|---|
| Tab | Moves focus into the group, landing on the last-focused toggle — or the first one. The whole group is a single tab stop. |
| ArrowRight then ArrowDown | Moves focus to the next toggle without pressing it, wrapping from the last to the first. Only the arrows on the group's own axis are bound. |
| ArrowLeft then ArrowUp | Moves focus to the previous toggle, wrapping from the first to the last. |
| Home then End | Moves focus to the first or last toggle. |
| Space then Enter | Presses the focused toggle. Moving focus never presses anything. |
Disabled toggles are skipped by the arrow keys as well as removed from the tab
order. Set loopFocus={false} to stop the arrows wrapping at the ends.
Each toggle still needs its own name too: text children, or an aria-label when
it is icon-only. See Toggle for the rest — the pressed
state, forced colours and motion all belong to the individual button.
Theming
The group declares its own properties on the group element; the toggles inside
are themed through the --forte-toggle-* properties documented on
Toggle.
| Property | Controls | Default |
|---|---|---|
--forte-toggle-group-gap | Gap between toggles. var(--forte-space-1) when segmented. | var(--forte-space-2) |
--forte-toggle-group-padding | Padding inside the strip. var(--forte-space-1) when segmented. | 0px |
--forte-toggle-group-radius | Corner radius of the strip. var(--forte-radius-4) when segmented. | 0px |
--forte-toggle-group-bg | Fill behind the strip. var(--forte-color-panel) when segmented. | transparent |
--forte-toggle-group-border-width | Border width of the strip. | 1px |
--forte-toggle-group-border-color | Border colour of the strip. | transparent |
API reference
ToggleGroup
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | Additional class name(s). Applied after the internal styles so consumer utilities (e.g. Tailwind) win without needing `!important`. | |
defaultValue | readonly Value[] | The values pressed on mount when uncontrolled. | |
disabled | boolean | false | Disable every toggle in the group. |
fullWidth | boolean | false | Stretch the group to fill its container and share the space equally between the toggles. Mostly useful with `segmented`, where an evenly divided strip is the expected shape. |
multiple | boolean | false | Allow several toggles to be pressed at once. With it off, pressing one unpresses the rest — but pressing the pressed one still turns it off, so "nothing selected" stays reachable in a way a radio group never allows. |
orientation | ToggleGroupOrientation | horizontal | Direction the toggles are laid out in, and the axis the arrow keys move along. Unlike `RadioGroup`'s, this is not layout-only: Base UI binds the arrows to the named axis, so a vertical group answers to Up and Down and leaves Left and Right to the page. |
ref | Ref<HTMLDivElement> | Ref to the group element. Declared as a prop rather than through `forwardRef` because the component is generic — a `forwardRef` wrapper would erase `Value` and with it the typing of `onValueChange`. | |
segmented | boolean | false | Draw the group as a segmented control: one padded panel behind the whole set, with the toggles closed up inside it. Off, the group is just a row of separate buttons — right for a toolbar, where the toggles are neighbours rather than alternatives. Pair it with `variant="solid"` for the classic filled segmented control. |
size | ToggleSize | md | Default `size` for every `Toggle` inside the group. A toggle's own `size` still wins. |
tone | ToggleTone | primary | Default `tone` for every `Toggle` inside the group. A toggle's own `tone` still wins. |
value | readonly Value[] | The values of every pressed toggle. Pairs with `onValueChange` for a controlled group; use `defaultValue` for an uncontrolled one. Always an array, including when `multiple` is false — it is then empty or holds one value. | |
variant | ToggleVariant | soft | Default `variant` for every `Toggle` inside the group. A toggle's own `variant` still wins. |
onValueChange, loopFocus, render and the rest of Base UI's ToggleGroup
props pass through unchanged.
Toggle
See Toggle for the full prop table.