---
title: "Toggle Group"
description: "Two-state toggle buttons, standalone or grouped into a single- or multi-select set."
links:
  doc: https://cladd.io/react/components/toggle-group/
  api: https://cladd.io/react/components/toggle-group/#api-reference
---

# 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`](/react/components/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`](/react/components/toolbar/) strips of editors and dashboards — view switches, format marks, alignment — so most of the examples below sit in one.

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

## Usage

```tsx
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`](/react/components/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.

```tsx
<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`](/react/components/button/) that remembers whether it's on.

```tsx
<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.

```tsx
<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`](/react/components/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`.

```tsx
<Toolbar size={size}>
  <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`](/react/components/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.

```tsx
<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.

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

## API Reference

### ToggleGroup

ToggleGroup accepts every [`Segmented`](/react/components/segmented/) prop (`color`, `variant`, `activeColor`, `activeVariant`, `activeOutline`, `outline`, `size`, `rounded`) in addition to those below.

**Generics:** `C extends ElementType = 'div'`

**Inherits from:** [`Segmented`](/react/components/segmented/)

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `defaultValue?` | `string \| string[]` | — | Initial selection (uncontrolled). Ignored when `value` is provided. |
| `multiple?` | `boolean` | `false` | Allow more than one selected value. Selection becomes an array and every `ToggleButton` toggles independently. Default `false`. |
| `onValueChange?` | `(value: string \| string[] \| undefined) => void` | — | Fires whenever the selection changes.<br>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`.<br>When provided, internal state is bypassed. |

### ToggleButton

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

**Generics:** `C extends ElementType = 'button'`

**Inherits from:** [`SegmentedButton`](/react/components/segmented-button/)

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `activeColor?` | `Color` | — | Accent color applied while **pressed**. Default: theme accent (or the group's `activeColor`). |
| `activeOutline?` | `boolean` | `true` | Outline ring while **pressed**. Default `true`. |
| `activeVariant?` | `SurfaceVariant` | `'gradient'` | `Surface` variant applied while **pressed**. Default `'gradient'`. |
| `defaultSelected?` | `boolean` | — | Initial pressed state for **standalone** use (uncontrolled). Ignored inside a `ToggleGroup`. |
| `onChange?` | `(selected: boolean, event: MouseEvent) => void` | — | Fires with the next pressed state on click. Standalone only - inside a `ToggleGroup` use the group's `onValueChange` instead. |
| `selected?` | `boolean` | — | Controlled pressed state for **standalone** use. Ignored inside a `ToggleGroup`. |
| `value?` | `string` | — | Identifies this button inside a `ToggleGroup` - matched against the group's selection.<br>Omit when using the button standalone. |
