<!-- Generated by scripts/gen-docs.mts from the JSDoc in registry/. Do not edit; run `pnpm run docs`. -->

# ToggleGroup

A row of related toggles that share one value, such as text alignment or bold, italic and underline in a toolbar. One toggle is pressed at a time unless `multiple` is set, which makes the value a list. The arrow keys move between toggles, and each keeps its name with `aria-pressed` for its state.

```tsx
import { ToggleGroup } from "@/components/ouro/toggle/toggle-group";
```

## Example

```tsx
<ToggleGroup
  label="Text style"
  hideLabel
  multiple
  items={[
    { value: "bold", label: "Bold", icon: BoldIcon, hideLabel: true },
    { value: "italic", label: "Italic", icon: ItalicIcon, hideLabel: true },
  ]}
  value={styles}
  onValueChange={setStyles}
/>
```

## Use instead when

- Use `SegmentedControl` instead when exactly one choice is always selected and switches a view.
- Use `RadioGroup` or `CheckboxGroup` instead for a form value that is submitted, and one `Toggle` for a single on/off button.

## Props

The props the modes share. Type: `ToggleGroupProps`.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `className` | `string` |  | Layout only: margins, grid placement (`mt-4`). Appearance classes warn in development. |
| `disabled` | `boolean` |  | Disables every toggle. |
| `hideLabel` | `boolean` |  | Hides the group's label visually; it still names the group. Set it on a toolbar whose toggles say what it is. |
| `items` (required) | `readonly ToggleGroupItem[]` |  | The toggles, in order. |
| `label` (required) | `string` |  | Names the group ("Text style"). Shown above it unless `hideLabel` is set; screen readers always hear it. |
| `ref` | `Ref<HTMLDivElement>` |  | Reaches the group element (`role="group"`). |
| `size` | `"sm" \| "md" \| "lg"` | `"md"` | Every toggle's size, as Button's. shadcn's `default` is `md`. |
| `variant` | `"outline" \| "plain"` | `"plain"` | `plain` toggles have no border until pressed; `outline` ones always have one. shadcn's `default` is `plain`. |

## Modes

`ToggleGroupProps` is a union: pass the props of exactly one mode. Mixing them is a type error.

### Multiple: `ToggleGroupMultipleProps`

With `multiple`, any number of toggles pressed: the value is a list of item values.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `defaultValue` | `readonly string[]` | [] | The toggles pressed first, when the group keeps its own state. |
| `multiple` (required) | `true` |  | Allows several toggles pressed at once, and makes the value a list. |
| `onValueChange` | `((value: string[]) => void)` |  | Called with the pressed toggles' values, in item order. |
| `value` | `readonly string[]` |  | The pressed toggles' values, when you control them. Pair it with `onValueChange`. |

### Single: `ToggleGroupSingleProps`

One toggle pressed at a time, the default: the value is one item's value, or `null` for none.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `defaultValue` | `string \| null` | null | The toggle pressed first, when the group keeps its own state. |
| `multiple` | `false` |  | Allows several toggles pressed at once, and makes the value a list. |
| `onValueChange` | `((value: string \| null) => void)` |  | Called with the pressed toggle's value, or `null` when the pressed one is pressed again. |
| `value` | `string \| null` |  | The pressed toggle's value, or `null` for none, when you control it. Pair it with `onValueChange`. |

## Don't use

These are not props. Passing one fails the type check with the fix in the error, and in development a console message names the fix.

- `children`: Not a prop. The toggles come from `items`: `<ToggleGroup items={[{ value: "bold", label: "Bold" }]}>`.
- `onChange`: Not a prop. Ouro UI uses `onValueChange`, which gets the value: `<ToggleGroup onValueChange={(value) => ...}>`.
- `options`: Not a prop. Ouro UI uses `items`: `<ToggleGroup items={[{ value, label }]}>`.
- `type`: Not a prop. One toggle at a time is the default; `multiple` allows several: `<ToggleGroup multiple>`.

## `className` is for layout only

Pass margins, width and grid placement (`mt-4`, `w-full`, `col-span-2`). Your classes always win over Ouro UI's: ToggleGroup merges `className` last with `cn` (tailwind-merge), so a class that conflicts with its own replaces it.[^layout-classes]

Appearance comes from props, not classes. In development, a class that sets appearance logs one warning per component instance, naming the prop to use instead. A class sets appearance when, after its variants (`hover:`, `sm:`) and any `!` are removed, it starts with `bg-`, `text-`, `border-`, `rounded-`, `shadow-`, `font-`, `ring-`, `from-`, `via-`, `to-`, `fill-` or `stroke-`, or is `border`, `rounded`, `shadow` or `ring`, or has a `dark:` variant. Text wrapping, overflow and table layout classes (`text-wrap`, `text-ellipsis`, `border-collapse`) are layout and do not warn.

Alignment classes (`text-center`) warn too: set alignment on a parent element.

## Types

### `ToggleGroupItem`

One toggle in a `ToggleGroup`.

```ts
interface ToggleGroupItem {
  /** Identifies the toggle: `value`, `defaultValue` and `onValueChange` use it. Unique within the group. */
  value: string;
  /** The toggle's name, shown unless `hideLabel` is set. It stays the same while pressed. */
  label: string;
  /** Icon before the label, or alone with `hideLabel`. Pass the component: `icon: BoldIcon`. */
  icon?: ToggleIcon | undefined;
  /** Shows only the icon; the label stays the toggle's name for screen readers. */
  hideLabel?: boolean | undefined;
  /** Shows the toggle but keeps it from being pressed. */
  disabled?: boolean | undefined;
}
```

[^layout-classes]: test:registry/ouro/components/ouro/toggle/toggle-group.test.tsx::ToggleGroup > forwards its ref to the group and lets layout classes win on the root verify:testExists(registry/ouro/components/ouro/toggle/toggle-group.test.tsx::ToggleGroup > forwards its ref to the group and lets layout classes win on the root)
