Toggle Group
A segmented control of toggle buttons for switching views or filters, plus a standalone toggle button.
Preview
Installation
pnpm add @syntara/react @syntara/tokensimport { ToggleButtonGroup, ToggleButton } from '@syntara/react';Usage
import { ToggleButton, ToggleButtonGroup } from '@syntara/react';
export function Period() {
return (
<ToggleButtonGroup aria-label="Period" defaultSelectedKeys={['month']} disallowEmptySelection>
<ToggleButton id="week">Week</ToggleButton>
<ToggleButton id="month">Month</ToggleButton>
<ToggleButton id="year">Year</ToggleButton>
</ToggleButtonGroup>
);
}Examples
Sizes
Icon only
Items named with aria-label render square.
Multiple selection
Standalone toggle button
Narrow container
When the options don't fit on one row, they wrap onto another row inside the track. Every label stays whole and nothing scrolls sideways.
Accessibility
| Keys | Action |
|---|---|
| Tab | Moves focus into the group, then out of it. |
| Arrow keys | Move focus between items (direction follows the locale). |
| SpaceorEnter | Toggles the focused item. |
- Single selection renders a radiogroup of radios; multiple selection renders a toolbar of pressed buttons.
- The selected item is raised and bold-coloured, not colour-only.
- A standalone ToggleButton exposes aria-pressed.
- The selected segment differs by colour (text.default vs text.subtle), weight (medium vs regular) and elevation (a raised pill with shadow and rim), not colour alone.
- Reflow (WCAG 1.4.10): the group is never wider than its container. Segments that don't fit wrap onto another row inside the track, and a label longer than the track wraps inside its segment, so no label is cut off and the page never scrolls sideways. Arrow keys still follow the reading order, in both directions.
Guidelines
Do
- Use for 2–5 short, mutually related options that switch a view immediately.
- Name the group with aria-label or a visible heading.
- Use disallowEmptySelection when one option must always be active.
- Keep labels to one or two short words. On a narrow screen the segments wrap onto a second row rather than overflow, but one row reads best.
Don’t
- Don't use it for form choices that are submitted later; use RadioGroup.
- Don't use it for more than 5 options or for long labels. Use Select to pick from a longer list, or Tabs when each option shows its own panel.
API reference
ToggleButtonGroup
selectionModesingledefaultmultiple
Whether one or several items can be on.
selectedKeys / defaultSelectedKeysIterable<Key>Controlled / uncontrolled selection, by item id.
onSelectionChange(keys: Set<Key>) => voidCalled when the selection changes.
disallowEmptySelectionbooleanKeep one item selected (typical for a segmented control).
Default
falsesizesmmddefault
md matches the control height (and a field or Button of the same size); sm is one 8px step smaller, never letting a segment drop under 24px. The track pads the pill by 4px (sm: 3px) and its corner is the pill's corner plus that padding.
orientationhorizontaldefaultvertical
Layout and arrow-key direction.
isDisabledbooleanDisables every item.
Default
falsearia-labelstringNames the group (or use aria-labelledby).
ToggleButton
idKeyRequired inside a group; the selection key.
isSelected / defaultSelectedbooleanStandalone only: controlled / uncontrolled pressed state.
onChange(isSelected: boolean) => voidStandalone only: called when toggled.
sizesmmddefault
Standalone only; inside a group the group's size wins.
aria-labelstringRequired for icon-only items; also makes the item square.
Tokens
The semantic tokens this component reads, grouped by what they control. Swatches show this site’s theme; change a tenant’s brand and the component follows with no code change.
- Colour12
border.defaultborder.strongborder.subtlefocus.ringsurface.defaultsurface.raisedsurface.selectedsurface.sunkentext.brandtext.defaulttext.disabledtext.subtle- Type5
font.size.mdfont.size.smfont.weight.mediumline-height.tightfont.weight.regular- Space and size6
control-heightcontrol-padding-inlinespace.1space.2space.4space.6- Shape1
radius.field- Depth3
shadow.highlightshadow.raisedhairline- Motion5
motion.duration.fastmotion.duration.springmotion.easingmotion.springmotion.duration.normal- Other1
rim