Skip to content

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/tokens
import { 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

KeysAction
TabMoves focus into the group, then out of it.
Arrow keysMove focus between items (direction follows the locale).
SpaceorEnterToggles 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

selectionMode
  • singledefault
  • multiple

Whether one or several items can be on.

selectedKeys / defaultSelectedKeys
Iterable<Key>

Controlled / uncontrolled selection, by item id.

onSelectionChange
(keys: Set<Key>) => void

Called when the selection changes.

disallowEmptySelection
boolean

Keep one item selected (typical for a segmented control).

Default false

size
  • sm
  • mddefault

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.

orientation
  • horizontaldefault
  • vertical

Layout and arrow-key direction.

isDisabled
boolean

Disables every item.

Default false

aria-label
string

Names the group (or use aria-labelledby).

ToggleButton

id
Key

Required inside a group; the selection key.

isSelected / defaultSelected
boolean

Standalone only: controlled / uncontrolled pressed state.

onChange
(isSelected: boolean) => void

Standalone only: called when toggled.

size
  • sm
  • mddefault

Standalone only; inside a group the group's size wins.

aria-label
string

Required 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