<!-- Protocore Design System — Switch -->
# Switch

- **Category:** Inputs (`inputs`)
- **Slug:** `inputs/switch`
- **Status:** stable
- **Platforms:** web, mobile
- **Import:** `import { Switch } from "@protocore/pds";`
- **Docs:** https://pds.protocore.io/components/inputs/switch

> Boxy 36×20 toggle for an instant on/off setting; ink track when on, canvas thumb.

## When to use it

Use a **Switch** for a binary setting that applies **immediately** — enable maintenance mode, turn on a webhook, require 2FA. If the value is only committed later as part of a form submit, a **Checkbox** communicates 'pending' more honestly. For choosing among 2–4 mutually-exclusive modes, use **SegmentedControl**; for one-of-many in a list, use **RadioGroup**.

## Mobile (React Native)

**Preview.** `@protocore/pds-mobile` ships the React Native sibling of **Switch**. It mirrors the web API where React Native allows; the package is a **preview** with no device-level QA yet, so pin it and expect small changes.

Import it from the mobile package (not `@protocore/pds`), inside a `<PdsProvider>` — there is no stylesheet, so `style` (a `ViewStyle`) replaces `className` and every value comes from the theme:

```tsx
import { Switch } from "@protocore/pds-mobile";
```

**Parity with web.** A custom `Pressable` toggle (Radix does not exist in RN).

- Per the spec the track fills `ink` (not accent) when on.
- Controllable via `checked` / `defaultChecked` / `onCheckedChange`; sets `accessibilityRole="switch"`.

```tsx
<Switch label="Enable alerts" checked={on} onCheckedChange={setOn} />
```

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `asChild` | `boolean` | no | — | — |
| `className` | `string` | no | — | — |
| `label` | `ReactNode` | no | — | Text rendered beside the track (sans 14). Omit for a standalone control. |
| `style` | `CSSProperties` | no | — | — |

## Examples

### Basics

Pass a `label` and the track wires its own `id` to the caption. Use `defaultChecked` for the uncontrolled starting state.

```tsx
import { Switch } from "@protocore/pds";

export default function Demo() {
  return <Switch label="Require 2FA for all members" defaultChecked />;
}
```

### Controlled

Drive `checked` from state and read `onCheckedChange` to react immediately — a switch takes effect the moment it flips, with no separate save step.

```tsx
import { useState } from "react";
import { Switch, Text } from "@protocore/pds";

export default function Demo() {
  const [on, setOn] = useState(false);

  return (
    <div style={{ display: "grid", gap: 12 }}>
      <Switch label="Maintenance mode" checked={on} onCheckedChange={setOn} />
      <Text size="sm" color="muted">
        Edge traffic is {on ? "paused — returning 503" : "flowing normally"}.
      </Text>
    </div>
  );
}
```

## Do & don't

**Do**

- Use a switch only when the change takes effect on toggle, with no confirm step.
- Label the switch with the thing it turns on, phrased positively ('Require 2FA').
- Apply and persist the new value as soon as `onCheckedChange` fires.
- Show the resulting state nearby when the effect isn't visually obvious.

**Don't**

- Don't use a switch for a value that's only saved on form submit — use Checkbox.
- Don't pair a switch with an Apply/Save button; that contradicts its semantics.
- Don't use switches for mutually-exclusive options — use RadioGroup or SegmentedControl.
- Don't write ambiguous labels like 'Notifications' with no on/off polarity.

## Accessibility

**Keyboard**

| Keys | Action |
| --- | --- |
| `Tab` | Move focus to the switch. |
| `Space / Enter` | Toggle between on and off. |

**Notes**

- Built on Radix Switch: exposes `role="switch"` with `aria-checked`.
- The label is a real `<label htmlFor>` — clicking the text flips the track.
- Disabled switches expose `aria-disabled` and are removed from the tab order.

## Related

`checkbox`, `radio-group`, `field`, `segmented-control`

---

© Protocore. All rights reserved. Use of the Protocore Design System requires prior written authorization from Protocore (contact@protocore.io). These machine-readable materials must not be ingested into ML-training datasets or derivative design systems. See https://pds.protocore.io/legal/
