{
  "title": "Toggle",
  "description": "A two-state button — standalone for toolbar actions, or clustered as Toggle.Group for radiogroup-style choices.",
  "url": "/docs/components/toggle",
  "since": "0.3.0",
  "tags": [
    "control",
    "form",
    "toolbar"
  ],
  "platform": "both",
  "source": "---\ntitle: Toggle\ndescription: A two-state button — standalone for toolbar actions, or clustered as Toggle.Group for radiogroup-style choices.\nsince: 0.3.0\ntags: [control, form, toolbar]\nplatform: both\ncategory: controls\n---\n\nimport { BundleSize } from '@/components/bundle-size';\nimport { Callout } from 'fumadocs-ui/components/callout';\nimport { Preview } from '@/components/preview';\nimport { PropsTable } from '@/components/props-table';\n\n<BundleSize component=\"Toggle\" />\n\n## At a glance\n\n- A single bistable button — think of the **B** / **I** / **U** buttons in a rich-text toolbar.\n- Cluster several with `<Toggle.Group>` for shared selection semantics (toolbar-multiple, alignment-single).\n- ARIA: `role=\"button\"` + `aria-pressed` per item. `<Toggle.Group>` adds `role=\"group\"` (multiple) or `role=\"radiogroup\"` (single).\n\n<Callout title=\"Toggle vs Switch vs Checkbox vs SegmentedControl\">\n    These four controls look similar but ship different semantics — pick the one that matches the *meaning* of the choice, not the shape of the visual.\n\n    - **Toggle** — a button with on/off state. Use it for toolbar-style actions (Bold, Pin, Mute). Lives outside `<form>`.\n    - **Toggle.Group** (`type=\"single\"`) — a cluster where one or none can be active. Re-clicking the active item clears it. Use this when \"no selection\" is a valid state.\n    - **[SegmentedControl](/docs/components/segmented-control)** — exactly one is always active. Use when \"no selection\" isn't a valid state.\n    - **Switch** — a setting that takes effect immediately (\"Dark mode\", \"Email notifications\"). Reads as `role=\"switch\"`.\n    - **Checkbox** — a value selected as part of a form. Reads as `role=\"checkbox\"`.\n</Callout>\n\n## Standalone Toggle\n\n<Preview name=\"toggle-basic\" />\n\n## `pressed` and `defaultPressed`\n\nControlled mode: pass `pressed` and pair with `onChange`. Uncontrolled\nmode: pass `defaultPressed` and let the Toggle track state.\n\n```tsx\n// Controlled\nconst [bold, setBold] = useState(false);\n<Toggle pressed={bold} onChange={setBold}>B</Toggle>\n\n// Uncontrolled\n<Toggle defaultPressed>I</Toggle>\n```\n\n## `variant`\n\nVisual treatment of the toggle when off and on.\n\n| Value             | Off state                  | On state                                     |\n|-------------------|----------------------------|----------------------------------------------|\n| `default` (default) | Subtle border + bg       | Tinted background + accent border            |\n| `outline`         | 1px border, no fill        | Tinted background + accent border            |\n\n```tsx\n<Toggle variant=\"outline\">Pin</Toggle>\n```\n\n## `size`\n\nDensity. Aligned with Button's scale.\n\n| Value             | Min height |\n|-------------------|------------|\n| `sm`              | 32 px      |\n| `md` (default)    | 36 px      |\n| `lg`              | 44 px      |\n\n```tsx\n<Toggle size=\"sm\">B</Toggle>\n```\n\n## `disabled`\n\nGreys the toggle out and blocks press handling. Forwarded as\n`aria-disabled`.\n\n```tsx\n<Toggle disabled>Locked</Toggle>\n```\n\n## `aria-label` / `accessibilityLabel`\n\nWhen the visible content is just an icon, pass `aria-label` (web) or\n`accessibilityLabel` (native) so screen readers say something\nmeaningful.\n\n```tsx\n<Toggle aria-label=\"Bold\"><BoldIcon /></Toggle>\n```\n\n## `<Toggle.Group>`\n\nClusters several Toggle items with shared selection semantics.\nRoving-tabindex keyboard nav follows the WAI-ARIA radiogroup pattern:\narrow keys move focus, `Home` / `End` jump to the ends, `Space` /\n`Enter` toggles the focused item. Default-variant grouped items share\nborders so the cluster reads as one segmented chip — first item rounds\nthe left, last rounds the right.\n\n### `type` — multiple vs single\n\nThe shape of `value` follows from `type`:\n\n| `type`         | `value` type           | Re-click behavior                        |\n|----------------|------------------------|------------------------------------------|\n| `multiple`     | `string[]`             | Toggles the item in / out of the array   |\n| `single`       | `string \\| undefined`  | Re-clicking the active item clears it    |\n\n#### Multiple selection (formatting toolbar)\n\n`type=\"multiple\"` — `value` is `string[]`. Clicking adds or removes an\nitem from the array.\n\n<Preview name=\"toggle-group-multiple\" />\n\n#### Single selection (alignment)\n\n`type=\"single\"` — `value` is `string | undefined`. Clicking sets it;\nclicking the active item again clears it.\n\n<Preview name=\"toggle-group-single\" />\n\n### `value` and `defaultValue`\n\nControlled (`value` + `onChange`) vs uncontrolled (`defaultValue`).\nTheir shapes follow `type`.\n\n```tsx\n<Toggle.Group type=\"multiple\" value={['bold', 'italic']} onChange={setMarks}>\n    <Toggle.Item value=\"bold\">B</Toggle.Item>\n    <Toggle.Item value=\"italic\">I</Toggle.Item>\n</Toggle.Group>\n\n<Toggle.Group type=\"single\" defaultValue=\"left\">\n    <Toggle.Item value=\"left\">L</Toggle.Item>\n    <Toggle.Item value=\"center\">C</Toggle.Item>\n    <Toggle.Item value=\"right\">R</Toggle.Item>\n</Toggle.Group>\n```\n\n### `onChange`\n\nFires with the next `value` whenever the user toggles an item. Pair\nwith `value` for controlled, omit for uncontrolled.\n\n```tsx\n<Toggle.Group type=\"multiple\" onChange={(marks) => editor.setMarks(marks)}>\n    {/* … */}\n</Toggle.Group>\n```\n\n### `disabled`\n\nDisables every item in the group. Individual items can still set\ntheir own `disabled`.\n\n```tsx\n<Toggle.Group disabled type=\"single\" defaultValue=\"bold\">{/* … */}</Toggle.Group>\n```\n\n### `variant` and `size` (group-level)\n\nForwarded to every item by default — set the cluster's look once and\nitems inherit. Per-item `variant` / `size` overrides the group value.\n\n```tsx\n<Toggle.Group variant=\"outline\" size=\"sm\" type=\"single\">{/* … */}</Toggle.Group>\n```\n\n### `aria-label` / `accessibilityLabel`\n\nThe group's accessible name. Required for assistive tech to announce\nthe cluster (\"Text formatting, group\"). For icon-only items inside,\ngive each item its own `aria-label` too.\n\n```tsx\n<Toggle.Group aria-label=\"Text formatting\" type=\"multiple\">\n    <Toggle.Item value=\"bold\" aria-label=\"Bold\">B</Toggle.Item>\n    <Toggle.Item value=\"italic\" aria-label=\"Italic\">I</Toggle.Item>\n</Toggle.Group>\n```\n\n## Props\n\n### `<Toggle>`\n\n<PropsTable component=\"Toggle\" />\n\n### `<Toggle.Group>`\n\n<PropsTable component=\"ToggleGroup\" />\n\n### `<Toggle.Item>`\n\n<PropsTable component=\"ToggleGroupItem\" />\n"
}
