# Switch

Package: @commenda/pathfinder@0.1.0
Page: /docs/components/switch
Figma: https://www.figma.com/design/dn7BkGYEfIyP0o2zfesfVh/The-System?node-id=199-4

```tsx
import { Switch } from '@commenda/pathfinder/switch';

<Switch label="Weekly summary" />;
```


## Installation [#installation]

```sh
pnpm --filter your-app add "@commenda/pathfinder@workspace:*"
```

Import `@commenda/pathfinder/styles.css` once at the app root. The stylesheet is precompiled with Tailwind v4; your application does not need Tailwind or source scanning. Event handlers belong in a client component in Next.js App Router.

## Usage [#usage]

```tsx
import { Switch } from '@commenda/pathfinder/switch';

<Switch
  label="Weekly summary"
  description="Sent each Monday."
  checked={weeklySummary}
  onCheckedChange={onWeeklySummaryChange}
/>;
```

| Prop                   | Type                         | Default / behavior                                           |
| ---------------------- | ---------------------------- | ------------------------------------------------------------ |
| `label`                | `string`                     | Required stable setting name                                 |
| `hideLabel`            | `boolean`                    | `false`; accessible name retained                            |
| `description`          | `string`                     | Optional supporting explanation                              |
| `checked`              | `boolean`                    | Controlled state                                             |
| `defaultChecked`       | `boolean`                    | `false`; uncontrolled initial state                          |
| `onCheckedChange`      | `(checked: boolean) => void` | Next state; application owns persistence                     |
| `disabled`             | `boolean`                    | Disables interaction for the control or group.               |
| `readOnly`             | `boolean`                    | Keeps the current value visible while preventing changes.    |
| `required`             | `boolean`                    | Requires a value for native form validation.                 |
| `disabledReason`       | `string`                     | Visible, associated explanation while disabled               |
| `name`                 | `string`                     | Name used when the control submits its value with a form.    |
| `value`                | `string`                     | Value submitted when checked; defaults to 'on'.              |
| `uncheckedValue`       | `string`                     | Value submitted when unchecked; omitted when not configured. |
| `form`                 | `string`                     | ID of the form associated with the control.                  |
| `id`                   | `string`                     | ID of the underlying form input.                             |
| `inputRef`             | `Ref<HTMLInputElement>`      | Access to the underlying form input.                         |
| `className`            | `string`                     | Additional class names for the outer layout.                 |
| `ref`                  | `Ref<HTMLElement>`           | Access to the interactive root element.                      |
| Native events and ARIA | Base UI root props           | Typed passthrough                                            |

A switch applies immediately. Keep its label the same in both states, such as “Weekly summary”, rather than “Turn on weekly summary”. On a failed asynchronous save, the application reverts the controlled state and explains the failure; this component does not invent persistence or loading/completion states. For form-save behavior use Checkbox, and for non-boolean choices use RadioGroup or SegmentedControl.

Track 36×20px, thumb 16px inset 2px, control elevation and 200ms ease-out movement. Honor reduced motion and RTL; coarse-pointer layouts provide at least a 44px row target without enlarging the visual control.

## Examples [#examples]

### Off and on [#off-and-on]


```tsx
<>
  <Switch label="Weekly summary" />
  <Switch label="Filing reminders" defaultChecked />
</>;
```


### Description [#description]


```tsx
<Switch label="Weekly summary" description="Sent each Monday." />;
```


### Disabled states [#disabled-states]


```tsx
<>
  <Switch label="Weekly summary" disabled />
  <Switch
    label="Filing reminders"
    defaultChecked
    disabled
    disabledReason="Administrator access required"
  />
</>;
```


Read the [Figma choice-control rules](/docs/components/switch#design-rules) for design guidance, source discrepancies and accessibility requirements.

## Design rules [#design-rules]

Figma guidance and reviewed implementation decisions for this component. Rule IDs remain stable for source comments and AI references.

### Switch [#switch]

Source: [199:4](https://www.figma.com/design/dn7BkGYEfIyP0o2zfesfVh/The-System?node-id=199-4), variants 200:5083, anatomy 207:148, guidance 207:184.

- **SWITCH-01** — Apply immediately with no separate Save action. Use Checkbox for changes saved later. Never use a switch to choose between two non-boolean options.
- **SWITCH-02** — The label names the setting and remains unchanged between states. Show results immediately; if persistence fails, the application reverts the controlled state and explains why. No invented loading/completion status is part of this API.
- **SWITCH-03** — Track 36×20px, radius full. Thumb 16px with 2px inset and Elevation/control. Off soft-pearl-400, on blue-700; hover soft-pearl-500/blue-800. Move the thumb 200ms ease-out; turn movement off for reduced motion and reverse travel in RTL. Label starts 8px from track, with 2px top alignment.
- **SWITCH-04** — Disabled off uses soft-pearl-100 track with soft-pearl-300 edge; disabled on uses soft-pearl-300 track. Thumb uses soft-pearl-200 without shadow. Keep the label readable with soft-pearl-600.

### Implementation decisions and source differences [#implementation-decisions-and-source-differences]

The complete prop tables are on [Checkbox](/docs/components/checkbox), [RadioGroup](/docs/components/radio-group) and [Switch](/docs/components/switch). Source rule IDs are also kept in the component implementation comments and exported through `llms.txt`, `llms-full.txt` and the Markdown routes.

- **CHOICE-01** — The sheets describe 8px list gaps but some documentation frames place rows 32px apart. Use the documented 8px component-list gap; documentation specimen whitespace is not a new size token.

- **CHOICE-02** — Built-in text is plain, wrapping content. Do not place links, buttons or nested interactive controls inside labels or cards. Disabled reasons are visible descriptions, not tooltip-only explanations on controls removed from keyboard navigation.

- **CHOICE-03** — Visual control size is not the hit target. Coarse-pointer rows provide at least 44px height, while preserving 16px marks and the 36×20px switch track. Cards already exceed this height.

- **CHOICE-04** — Hover/focus are real browser states, not public cosmetic props. Retain native `name`, `value`, `form`, `required`, `readOnly`, disabled semantics and input refs. `hideLabel` preserves the required accessible label.

- **CHOICE-05** — Use Pathfinder's existing Check/Minus optical artwork at 12px. Boxes, circles, tracks and thumbs are interactive primitive geometry, styled with the Figma tokens; they are not flattened screenshots. This keeps focus, RTL and switch movement functional.

### Explicit differences and boundaries [#explicit-differences-and-boundaries]

| Reference                                                                                         | Coverage                                                                                                                                                                          |
| ------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Editing 442:767](https://www.figma.com/design/dn7BkGYEfIyP0o2zfesfVh/The-System?node-id=442-767) | Account mapping demonstrates select, numeric validation, outline toggle, failed-save recovery and Add line. The companion example composes date, Switch and attachment selection. |
