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

# Toggle

A button that stays pressed until it is pressed again, such as Bold in a text toolbar. It keeps one name (`label`) and reports its state with `aria-pressed`; a pressed toggle gets the primary tint. Pass `icon` with `hideLabel` for an icon-only toggle; it has a 44px touch target on phones.

```tsx
import { Toggle } from "@/components/ouro/toggle/toggle";
```

## Example

```tsx
<Toggle label="Bold" icon={BoldIcon} hideLabel pressed={bold} onPressedChange={setBold} />
<Toggle label="Show completed" variant="outline" defaultPressed />
```

## Use instead when

- Use `ToggleGroup` instead for a row of related toggles with arrow-key focus.
- Use `Switch` instead for a setting that takes effect at once, and `Checkbox` for a form value.

## Props

Type: `ToggleProps`.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `className` | `string` |  | Layout only: margins, grid placement (`mt-4`). Appearance classes warn in development; use `variant` and `size` instead. |
| `defaultPressed` | `boolean` | `false` | Whether the toggle starts on, when it keeps its own state. |
| `disabled` | `boolean` |  | Keeps the toggle from being pressed, and fades it. |
| `hideLabel` | `boolean` |  | Shows only the icon; the label stays the toggle's name for screen readers. Pass `icon` with it. |
| `icon` | `ToggleIcon` |  | Icon before the label, or alone with `hideLabel`. Pass the component, not an element: `icon={BoldIcon}`. |
| `label` (required) | `string` |  | What the toggle turns on, such as "Bold". It is the button's name and stays the same while pressed: `aria-pressed` says whether it is on. Required: every toggle needs a name. |
| `onPressedChange` | `((pressed: boolean) => void)` |  | Called with the new state when the person presses the toggle. |
| `pressed` | `boolean` |  | Whether the toggle is on, when you control it. Pair it with `onPressedChange`. |
| `ref` | `Ref<HTMLButtonElement>` |  | The button element. |
| `size` | `"sm" \| "md" \| "lg"` | `"md"` | Control size, as Button's: each is taller on phones and steps down to desktop density from the `sm` breakpoint with a fine pointer. shadcn's `default` is `md`. |
| `variant` | `"outline" \| "plain"` | `"plain"` | `plain` has no border until pressed; `outline` always has one. Either way a pressed toggle gets the primary tint. shadcn's `default` is `plain`. |

## Native attributes

Also accepts the attributes in React's `ButtonHTMLAttributes` and `HTMLAttributes` (`id`, `aria-*`, event handlers), passed to the rendered element, except those named on this page.

## 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.

- `active`: Not a prop. Ouro UI uses `pressed`: `<Toggle pressed>`.
- `checked`: Not a prop. A toggle is pressed, not checked: `<Toggle pressed>`. For a setting, use `Switch`.
- `children`: Not a prop. The label is a prop, so the toggle always has a name: `<Toggle label="Bold">`.
- `defaultChecked`: Not a prop. A toggle is pressed, not checked: `<Toggle defaultPressed>`.
- `isPressed`: Not a prop. Ouro UI uses `pressed`: `<Toggle pressed>`.
- `isSelected`: Not a prop. Ouro UI uses `pressed`: `<Toggle pressed>`.
- `onChange`: Not a prop: a button's change event never fires. Use `onPressedChange`: `<Toggle onPressedChange={(pressed) => ...}>`.
- `onCheckedChange`: Not a prop. Ouro UI uses `onPressedChange`: `<Toggle onPressedChange={(pressed) => ...}>`.
- `selected`: Not a prop. Ouro UI uses `pressed`: `<Toggle pressed>`.
- `startIcon`: Not a prop. Ouro UI uses `icon`: `<Toggle icon={BoldIcon}>`.
- `tone`: Not a prop. A pressed toggle uses the primary tint; `variant="outline"` adds a border.

## `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: Toggle 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.

[^layout-classes]: test:registry/ouro/components/ouro/toggle/toggle.test.tsx::Toggle > lets app layout classes win verify:testExists(registry/ouro/components/ouro/toggle/toggle.test.tsx::Toggle > lets app layout classes win)
