Toggle Group

Pressable two-state buttons. ToggleButton works on its own as a press-to-hold control, or drop several into a ToggleGroup to make a single- or multi-select set. It builds on Segmented, so it inherits the same accent, variant, and size options — but where Segmented always keeps one option selected, a toggle can sit fully off. Like the rest of cladd's application controls, toggles are built for the dense Toolbar strips of editors and dashboards — view switches, format marks, alignment — so most of the examples below sit in one.

<Toolbar>
  <ToggleGroup value={view} onValueChange={setView}>
    <ToggleButton value="grid">Grid</ToggleButton>
    <ToggleButton value="list">List</ToggleButton>
    <ToggleButton value="board">Board</ToggleButton>
  </ToggleGroup>
</Toolbar>

Usage

import { ToggleGroup, ToggleButton } from '@cladd-ui/react';
 
<ToggleGroup defaultValue="grid">
  <ToggleButton value="grid">Grid</ToggleButton>
  <ToggleButton value="list">List</ToggleButton>
  <ToggleButton value="board">Board</ToggleButton>
</ToggleGroup>;

By default a group is single-select — pass a single string to value / defaultValue and read it back from onValueChange. Clicking the active button again deselects it, collapsing the selection to undefined. That's the difference from Segmented, which always keeps exactly one option chosen.

Examples

Multiple

Set multiple to let several buttons stay pressed at once. The selection becomes a string[] of the pressed values — a natural fit for text-format marks like bold, italic, and underline.

<Toolbar>
  <ToggleGroup multiple value={marks} onValueChange={setMarks}>
    <ToggleButton value="bold" aria-label="Bold">
      <BoldIcon />
    </ToggleButton>
    <ToggleButton value="italic" aria-label="Italic">
      <ItalicIcon />
    </ToggleButton>
    <ToggleButton value="underline" aria-label="Underline">
      <UnderlineIcon />
    </ToggleButton>
  </ToggleGroup>
</Toolbar>

Standalone

A ToggleButton used outside a group owns its own state. Leave it uncontrolled with defaultSelected, or control it with selected and onChange — like a Button that remembers whether it's on.

<ToggleButton defaultSelected>Mute</ToggleButton>
<ToggleButton selected={pinned} onChange={setPinned} activeColor="orange">
  {pinned ? 'Pinned' : 'Pin'}
</ToggleButton>

Colors

activeColor sets the accent applied while a button is pressed. It defaults to the theme accent and accepts any of the eleven accent colors.

<Toolbar>
  <ToggleGroup defaultValue="grid" activeColor={color}>
    <ToggleButton value="grid">Grid</ToggleButton>
    <ToggleButton value="list">List</ToggleButton>
    <ToggleButton value="board">Board</ToggleButton>
  </ToggleGroup>
</Toolbar>

Sizes

ToggleGroup follows the shared 2xs → 2xl size scale. Inside a Toolbar it picks up the toolbar's size, so the whole strip — chrome and buttons alike — scales from one prop; standalone, set size on the group and it forwards to every child ToggleButton. The default is md.

<Toolbar size="md">
  <ToggleGroup defaultValue="grid">
    <ToggleButton value="grid">Grid</ToggleButton>
    <ToggleButton value="list">List</ToggleButton>
    <ToggleButton value="board">Board</ToggleButton>
  </ToggleGroup>
</Toolbar>

Multiple groups

Pack several groups into one Toolbar and divide them with ToolbarSeparator — format marks as a multi-select set, alignment as single-select — for a dense, editor-grade control bar. Each group keeps its own selection while sharing the toolbar's size and rounded from context.

<Toolbar>
  <ToggleGroup multiple value={marks} onValueChange={setMarks}>
    <ToggleButton value="bold" aria-label="Bold">
      <BoldIcon />
    </ToggleButton>
    <ToggleButton value="italic" aria-label="Italic">
      <ItalicIcon />
    </ToggleButton>
    <ToggleButton value="underline" aria-label="Underline">
      <UnderlineIcon />
    </ToggleButton>
  </ToggleGroup>
  <ToolbarSeparator />
  <ToggleGroup value={align} onValueChange={setAlign}>
    <ToggleButton value="left" aria-label="Align left">
      <AlignLeftIcon />
    </ToggleButton>
    <ToggleButton value="center" aria-label="Align center">
      <AlignCenterIcon />
    </ToggleButton>
    <ToggleButton value="right" aria-label="Align right">
      <AlignRightIcon />
    </ToggleButton>
  </ToggleGroup>
</Toolbar>

Playground

The active-state knobs (activeColor, activeVariant), the shared size, and the multiple flag compose freely; the playground below combines them.

<Toolbar size="md">
  <ToggleGroup
    multiple={false}
    defaultValue={['grid']}
    activeColor="brand"
    activeVariant="gradient"
  >
    <ToggleButton value="grid">Grid</ToggleButton>
    <ToggleButton value="list">List</ToggleButton>
    <ToggleButton value="board">Board</ToggleButton>
  </ToggleGroup>
</Toolbar>

API Reference

ToggleGroup

ToggleGroup accepts every Segmented prop (color, variant, activeColor, activeVariant, activeOutline, outline, size, rounded) in addition to those below.

C extends ElementType = 'div'/Inherits from SegmentedProps
defaultValue: string | string[]Initial selection (uncontrolled). Ignored when value is provided.
multiple: booleanfalseAllow more than one selected value. Selection becomes an array and every ToggleButton toggles independently. Default false.
onValueChange: (value: string | string[] | undefined) => voidFires whenever the selection changes.

Receives a single value (or undefined when nothing is selected) in single-select mode, or the full array in multiple mode.
value: string | string[]Controlled selection. A single value in single-select mode, an array when multiple.

When provided, internal state is bypassed.

ToggleButton

ToggleButton extends Segmented's SegmentedButton (and through it Button), so the full button API is available. Inside a ToggleGroup it derives its pressed state from value; standalone it owns its own.

C extends ElementType = 'button'/Inherits from SegmentedButtonProps
activeColor: ColorAccent color applied while pressed. Default: theme accent (or the group's activeColor).
activeOutline: booleantrueOutline ring while pressed. Default true.
activeVariant: SurfaceVariant'gradient'Surface variant applied while pressed. Default 'gradient'.
defaultSelected: booleanInitial pressed state for standalone use (uncontrolled). Ignored inside a ToggleGroup.
onChange: (selected: boolean, event: MouseEvent) => voidFires with the next pressed state on click. Standalone only - inside a ToggleGroup use the group's onValueChange instead.
selected: booleanControlled pressed state for standalone use. Ignored inside a ToggleGroup.
value: stringIdentifies this button inside a ToggleGroup - matched against the group's selection.

Omit when using the button standalone.