# ToggleGroup

> A compact row of toggle buttons in a gray track, each one on or off on its own, or one of them or none; a pressed button is a yellow sticker.

Source: https://raft-design.botiverse.build/components/toggle-group. Generated from the current release; where it differs from what you remember, this page is right.

A toggle group is a row of buttons in a gray track that people press on and off: Bold, Italic and Underline, or a row of filters, each selectable on its own ([Built from existing parts](https://raft-design.botiverse.build/components.md#a-row-of-toggle-buttons)). With `multiple`, any number can be on; without it, one or none. A pressed button is a yellow sticker.

```tsx
import { Bold, Italic, Underline } from "lucide-react";
import { ToggleGroup, ToggleGroupItem, ToggleGroupLabel } from "@botiverse/raft-ui";

const DEFAULT_VALUE = ["bold"];

export function ToggleGroupFormattingComposition() {
  return (
    <ToggleGroup multiple defaultValue={DEFAULT_VALUE} aria-label="Text formatting">
      <ToggleGroupItem value="bold">
        <Bold aria-hidden />
        <ToggleGroupLabel>Bold</ToggleGroupLabel>
      </ToggleGroupItem>
      <ToggleGroupItem value="italic">
        <Italic aria-hidden />
        <ToggleGroupLabel>Italic</ToggleGroupLabel>
      </ToggleGroupItem>
      <ToggleGroupItem value="underline">
        <Underline aria-hidden />
        <ToggleGroupLabel>Underline</ToggleGroupLabel>
      </ToggleGroupItem>
    </ToggleGroup>
  );
}
```

## When to use

| Situation                                                   | Use                                                                                 |
| ----------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| Several options in a compact row, each on or off on its own | ToggleGroup with `multiple`                                                         |
| One option of a few, or none                                | ToggleGroup                                                                         |
| One of 2 to 4 views, and one is always selected             | [SegmentedControl](https://raft-design.botiverse.build/components/segmented-control.md)                       |
| Options that are saved with a form                          | [Checkbox](https://raft-design.botiverse.build/components/checkbox.md)                                                 |
| One setting, applied at once                                | [Switch](https://raft-design.botiverse.build/components/switch.md)                                                       |
| Filtering a list by one of its values                       | A filter ([PickerTriggerButton](https://raft-design.botiverse.build/components/picker-trigger-button.md)) |

The full table is in [Choosing a component](https://raft-design.botiverse.build/components.md#picking-something).

## Anatomy

- `ToggleGroup`: the track, in `fill-muted`. Its `value` is the list of pressed items. Required.
- `ToggleGroupItem`: one 32px button, identified by its `value`. Required, at least 2.
  - An icon: optional, 16px. It can stand alone (`aria-label` required, see [Accessibility](#accessibility)).
  - `ToggleGroupLabel`: the visible label. It truncates when the row is too narrow.

## Variants

| Variant                  | Use for                                                                                         |
| ------------------------ | ----------------------------------------------------------------------------------------------- |
| `multiple`               | Options that combine: Bold and Italic can both be on                                            |
| Without `multiple`       | Options that exclude each other, where none is also an answer: an alignment that can be cleared |
| `orientation="vertical"` | A stack of toggles in a narrow column                                                           |

```tsx
import { AlignCenter, AlignLeft, AlignRight } from "lucide-react";
import { ToggleGroup, ToggleGroupItem } from "@botiverse/raft-ui";

const DEFAULT_VALUE = ["left"];

export function ToggleGroupAlignmentComposition() {
  return (
    <ToggleGroup defaultValue={DEFAULT_VALUE} aria-label="Text alignment">
      <ToggleGroupItem value="left" aria-label="Align left">
        <AlignLeft aria-hidden />
      </ToggleGroupItem>
      <ToggleGroupItem value="center" aria-label="Align center">
        <AlignCenter aria-hidden />
      </ToggleGroupItem>
      <ToggleGroupItem value="right" aria-label="Align right">
        <AlignRight aria-hidden />
      </ToggleGroupItem>
    </ToggleGroup>
  );
}
```

```tsx
import { List, ListOrdered, Quote } from "lucide-react";
import { ToggleGroup, ToggleGroupItem, ToggleGroupLabel } from "@botiverse/raft-ui";

export function ToggleGroupVerticalComposition() {
  return (
    <ToggleGroup multiple orientation="vertical" aria-label="Block formatting">
      <ToggleGroupItem value="bulleted-list">
        <List aria-hidden />
        <ToggleGroupLabel>Bulleted list</ToggleGroupLabel>
      </ToggleGroupItem>
      <ToggleGroupItem value="numbered-list">
        <ListOrdered aria-hidden />
        <ToggleGroupLabel>Numbered list</ToggleGroupLabel>
      </ToggleGroupItem>
      <ToggleGroupItem value="quote">
        <Quote aria-hidden />
        <ToggleGroupLabel>Quote</ToggleGroupLabel>
      </ToggleGroupItem>
    </ToggleGroup>
  );
}
```

## States

| State                         | Look                                                                                                                                                                                                                                          |
| ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Not pressed                   | `foreground-muted` text on the track; the medium tier on hover and press                                                                                                                                                                      |
| Pressed                       | A yellow sticker with a bold label ([Color](https://raft-design.botiverse.build/foundations/color.md#stickers)). It doesn't change on hover; a press lays `sticker-medium` ([Hover and press](https://raft-design.botiverse.build/foundations/states.md#hover-and-press)) |
| Disabled item, disabled group | `foreground-disabled` text, no reaction to hover or press ([States](https://raft-design.botiverse.build/foundations/states.md))                                                                                                                             |

```tsx
import { Bold, Italic, Underline } from "lucide-react";
import { ToggleGroup, ToggleGroupItem, ToggleGroupLabel } from "@botiverse/raft-ui";

const DEFAULT_VALUE = ["bold"];

export function ToggleGroupItemDisabledComposition() {
  return (
    <ToggleGroup multiple defaultValue={DEFAULT_VALUE} aria-label="Text formatting">
      <ToggleGroupItem value="bold">
        <Bold aria-hidden />
        <ToggleGroupLabel>Bold</ToggleGroupLabel>
      </ToggleGroupItem>
      <ToggleGroupItem value="italic">
        <Italic aria-hidden />
        <ToggleGroupLabel>Italic</ToggleGroupLabel>
      </ToggleGroupItem>
      <ToggleGroupItem value="underline" disabled>
        <Underline aria-hidden />
        <ToggleGroupLabel>Underline</ToggleGroupLabel>
      </ToggleGroupItem>
    </ToggleGroup>
  );
}
```

```tsx
import { Bold, Italic, Underline } from "lucide-react";
import { ToggleGroup, ToggleGroupItem, ToggleGroupLabel } from "@botiverse/raft-ui";

const DEFAULT_VALUE = ["bold"];

export function ToggleGroupDisabledComposition() {
  return (
    <ToggleGroup multiple disabled defaultValue={DEFAULT_VALUE} aria-label="Text formatting">
      <ToggleGroupItem value="bold">
        <Bold aria-hidden />
        <ToggleGroupLabel>Bold</ToggleGroupLabel>
      </ToggleGroupItem>
      <ToggleGroupItem value="italic">
        <Italic aria-hidden />
        <ToggleGroupLabel>Italic</ToggleGroupLabel>
      </ToggleGroupItem>
      <ToggleGroupItem value="underline">
        <Underline aria-hidden />
        <ToggleGroupLabel>Underline</ToggleGroupLabel>
      </ToggleGroupItem>
    </ToggleGroup>
  );
}
```

## Behavior

- A horizontal group wraps its items onto a new row when they don't fit, and never grows wider than its container.
- Pressing a pressed item turns it off, in both variants.
- Items sit 3px inside the track and 3px apart, like the segments of a [SegmentedControl](https://raft-design.botiverse.build/components/segmented-control.md).
- Items are 32px high and don't extend their hit area to 44px. On touch screens that is below the [hit target](https://raft-design.botiverse.build/foundations/spacing.md#hit-targets).

## Content

- Label each item with what it turns on, in Title Case: Bold, Numbered List ([Writing](https://raft-design.botiverse.build/content/writing.md#casing)).

## Accessibility

- `ToggleGroup` wraps the Base UI ToggleGroup and each `ToggleGroupItem` the Base UI Toggle: every item is a button with `aria-pressed`, and the arrow keys move focus between items in the direction of `orientation`, wrapping at the ends (`loopFocus`).
- Name the group with `aria-label` after what it controls: "Text formatting", "Text alignment".
- Give every icon-only item an `aria-label` ("Align left"), and hide its icon (`aria-hidden`).

## Rules

- Don't use a toggle group to switch views or sections: one view is always shown, and a toggle group can be left with none. Use a [SegmentedControl](https://raft-design.botiverse.build/components/segmented-control.md) or [Tabs](https://raft-design.botiverse.build/components/tabs.md).

## API

### ToggleGroup

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `defaultValue` | `readonly T[]` |  | The pressed state of the toggle group represented by an array of the values of all pressed toggle buttons. This is the uncontrolled counterpart of `value`. |
| `disabled` | `boolean` | `false` | Whether the toggle group should ignore user interaction. |
| `loopFocus` | `boolean` | `true` | Whether to loop keyboard focus back to the first item when the end of the list is reached while using the arrow keys. |
| `multiple` | `boolean` | `false` | When `false` only one item in the group can be pressed. If any item in the group becomes pressed, the others will become unpressed. When `true` multiple items can be pressed. |
| `onValueChange` | `(groupValue: T[], eventDetails: BaseToggleGroup.ChangeEventDetails) => void` |  | Callback fired when the pressed states of the toggle group changes. |
| `orientation` | `Orientation` | `'horizontal'` |  |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |
| `value` | `readonly T[]` |  | The pressed state of the toggle group represented by an array of the values of all pressed toggle buttons. This is the controlled counterpart of `defaultValue`. |

Also takes the attributes of its element.

### ToggleGroupItem

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value` (required) | `T` |  | A unique string that identifies the toggle when used inside a toggle group. |
| `disabled` | `boolean` | `false` | Whether the component should ignore user interaction. |
| `nativeButton` | `boolean` | `true` | Whether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `false` if the rendered element is not a button (for example, `<div>`). |
| `onPressedChange` | `(pressed: boolean, eventDetails: BaseToggle.ChangeEventDetails) => void` |  | Callback fired when the pressed state is changed. |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### ToggleGroupLabel

Also takes the attributes of its element.

## Changes

- 0.3.0 (Added): Graduated `ProfilePanel` and `ToggleGroup` to the stable package entry point.
