Toggle Group

A row of attached toggles where one or several can be pressed.

Usage

Toggle Group attaches its Toggle children into one control and tracks which are pressed. By default pressing one unpresses the others; with multiple, any number stay pressed. The value is always an array of the pressed Toggles' values, also in single mode.

import { Toggle } from '@epilot/spark-ui/toggle'
import { ToggleGroup } from '@epilot/spark-ui/toggle-group'
function SourceFilter() {
  return (
    <ToggleGroup
      aria-label="Energy sources"
      multiple
      value={sources}
      onValueChange={setSources}
    >
      <Toggle value="solar">Solar</Toggle>
      <Toggle value="battery">Battery</Toggle>
      <Toggle value="grid">Grid</Toggle>
    </ToggleGroup>
  )
}

Use Toggle Group when several answers can apply at once (multiple), or when a single choice may also be cleared. For exactly one choice that always has a value, use Segmented Control. For a long list of options or options with descriptions, use Checkbox or Radio Card Group. For a row of unrelated actions, use Button Group.

Examples

Multiple

multiple lets any number of Toggles stay pressed.

Controlled

Pass value and onValueChange to keep the pressed values in your own state. onValueChange receives the full array, not the Toggle that changed.

email

Vertical

orientation="vertical" stacks the Toggles and switches arrow-key navigation to ArrowUp and ArrowDown.

Styles and size

styleVariant, color, and size on the group apply to every Toggle in it. Each is resolved per prop: a Toggle's own styleVariant, color, or size wins over the group's, so a Toggle with only color inside a styleVariant="soft" group is still soft. Unlike Button Group, styleVariant and color style only pressed Toggles; unpressed ones stay neutral. With neither set, a group looks like standalone Toggles, not like Button Group's soft neutral default.

Items in a soft group sit apart, like List's soft rows, and unpressed ones drop the outline for a light neutral fill, a step under the soft pressed fill; other groups glue them together, with a divider between two pressed solid items. Spacing follows the group, so give soft items a soft group rather than setting styleVariant="soft" on each.

showCheck on the group sets the default for every Toggle; a Toggle's own showCheck wins.

API Reference

ToggleGroup

Renders a Base UI Toggle Group. Children are Toggles, each with a value. Other Base UI props pass through.

PropTypeDefaultDescription
multiplebooleanfalseWhen false, pressing a Toggle unpresses the others. When true, any number stay pressed.
valuestring[]—Controlled pressed values. Provide onValueChange to update it. An array in single mode too.
defaultValuestring[]—Initial pressed values when uncontrolled.
onValueChange(value: string[], details) => void—Fires with the full array of pressed values after each change.
disabledbooleanfalseDisables every Toggle in the group.
orientation"horizontal" | "vertical""horizontal"Lays the Toggles out in a row or a column and picks the arrow keys that move focus.
loopFocusbooleantrueMoves focus from the last Toggle back to the first with the arrow keys, and the other way round.
styleVariant"solid" | "soft" | "surface"—The pressed look for every Toggle. Defaults to solid when only color is set.
color"primary" | "neutral" | "destructive"—The pressed accent color for every Toggle.
size"small" | "default" | "medium" | "icon-small" | "icon" | "icon-medium"—Size for every Toggle. A Toggle's own size wins.
showCheckbooleantrueDefault showCheck for every Toggle. A Toggle's own showCheck wins.
aria-labelstring—Names the group. Required unless aria-labelledby points at a visible label.
classNamestring—Merges with the base styles on the group container.

Accessibility

  • The group renders role="group" and each Toggle a <button> with aria-pressed. Pass aria-label or aria-labelledby so the group has a name.
  • The group is one tab stop. Arrow keys move focus between Toggles (ArrowLeft and ArrowRight, or ArrowUp and ArrowDown when vertical), and Enter or Space presses the focused one.
  • Keep each Toggle's label the same in both states; the pressed state is announced on its own.
  • The check drawn on a pressed Toggle is decorative (aria-hidden); state comes from aria-pressed.

On this page