{
  "title": "Switch",
  "description": "Binary on/off toggle with controlled and uncontrolled modes.",
  "url": "/docs/components/switch",
  "since": "0.1.0",
  "tags": [
    "control",
    "form"
  ],
  "platform": "both",
  "source": "---\ntitle: Switch\ndescription: Binary on/off toggle with controlled and uncontrolled modes.\nsince: 0.1.0\ntags: [control, form]\nplatform: both\ncategory: controls\n---\n\nimport { BundleSize } from '@/components/bundle-size';\nimport { ExpoSnack } from '@/components/expo-snack';\nimport { Preview } from '@/components/preview';\nimport { PropsTable } from '@/components/props-table';\n\n<BundleSize component=\"Switch\" />\n\n## At a glance\n\n- Renders with `role=\"switch\"` on web; maps to RN `<Switch>` on native, so the platform's native motion + haptics carry over on iOS / Android.\n- Use Switch for **immediate** state flips (settings that take effect on toggle). Reach for [Checkbox](/docs/components/checkbox) when the user is choosing items in a form they'll submit later.\n\n## Preview\n\n<Preview name=\"switch-basic\" />\n\n## `checked` and `defaultChecked`\n\nControlled vs. uncontrolled — same shape as Checkbox.\n\n```tsx\n// Controlled — parent owns the truth\nconst [enabled, setEnabled] = useState(false);\n<Switch checked={enabled} onChange={setEnabled} label=\"Email digest\" />\n\n// Uncontrolled — Switch tracks state itself\n<Switch defaultChecked label=\"Sync on Wi-Fi only\" />\n```\n\n## `label`\n\nRenders a clickable label next to the track. Pressing the label is the\nsame target as pressing the track itself, with a wider hit area.\n\n```tsx\n<Switch label=\"Show advanced options\" />\n```\n\n## Inline label vs Field\n\nThe `label` prop is the **inline** label (right of the track) — the control's own affordance.\nUse it for stand-alone toggles:\n\n```tsx\nimport { Switch } from '@nori-ui/core';\n\nexport const Example = () => (\n    <Switch label=\"Email digests\" />\n);\n```\n\nFor grouped settings with description and error, wrap in `<Field>`:\n\n```tsx\nimport { Field, Switch } from '@nori-ui/core';\n\nexport const Example = () => (\n    <Field label=\"Notifications\" description=\"Choose how you'd like to be notified.\">\n        <Switch label=\"Email digests\" />\n    </Field>\n);\n```\n\nSee [Field](/docs/components/field) for the full API. For custom layouts, use the [compound API](/docs/components/field#custom-layout-compound-api).\n\n## `onChange`\n\nFires with the next boolean. Pair with `checked` for controlled mode,\nomit for uncontrolled — the Switch calls it either way.\n\n```tsx\n<Switch onChange={(next) => savePreference(next)} />\n```\n\n## `disabled`\n\nGreys out the track and blocks `onChange`. Forwarded as\n`aria-disabled` so assistive tech narrates \"switch, disabled\".\n\n```tsx\n<Switch disabled label=\"Requires Pro plan\" />\n```\n\n## `asChild`\n\nRenders a supplied element as the interactive root. Same composition\npattern as Checkbox / Button — pass any focusable element to inherit\nthe Switch's behavior while keeping your own DOM shape.\n\n```tsx\n<Switch asChild>\n    <Pressable>\n        <YourCustomRow />\n    </Pressable>\n</Switch>\n```\n\n## Accessibility props\n\nWhen wrapping `Switch` in `<Field>`, the following attributes are injected\nonto the underlying control automatically:\n\n- `id` — matches the `htmlFor` of the label generated by `Field`.\n- `aria-labelledby` — references the `Field.Label` element's ID.\n- `aria-describedby` — references `Field.Description` and/or `Field.Error` when present.\n- `aria-invalid` — set when the enclosing `Field` has a non-null `error`.\n- `aria-required` — set when `Field` has `required={true}`.\n\nOn native, React Native equivalents are forwarded instead:\n`accessibilityLabelledBy` (mirrors `aria-labelledby`) and\n`accessibilityDescribedBy` (mirrors `aria-describedby`).\n\nYou can also pass any of these props explicitly when using `Switch` without a\n`Field` wrapper.\n\n## Native preview\n\n<ExpoSnack component=\"Switch\" height={300} />\n\n## Props\n\n<PropsTable component=\"Switch\" />\n"
}
