# Switch

## Overview

The switch component is a binary form control for immediately toggling a setting on or off.

The component pattern uses a native checkbox input with `role="switch"` inside a wrapping `<label>`, so it keeps checkbox form behavior while assistive technology can announce the control as a switch.

## When to use

Use a switch to toggle one setting on or off with an immediate effect.

## When not to use

Do not use a switch for agreement or selecting one or more items from a set; use a checkbox.

## Usage

```html
<label>
  <input type="checkbox" role="switch" name="notifications-enabled" checked />
  Notifications
</label>
```

Use this component when the user is toggling a single setting.

Use a checkbox instead when the user is selecting one or more items from a set, or when the control represents agreement rather than an on/off state.

The input should stay inside its wrapping `<label>` so the full text remains clickable without extra helper markup.

For switches with an obvious visual state pair, opt into icons with `data-switch-icons` and provide Material Symbols glyph names for both states:

```html
<label>
  <input
    type="checkbox"
    role="switch"
    name="dark-mode"
    data-switch-icons
    data-switch-on-icon="dark_mode"
    data-switch-off-icon="light_mode"
  />
  Dark mode
</label>
```

The icon attributes are:

- `data-switch-icons`: opts the switch into icon rendering and replaces the default `Off` and `On` track text.
- `data-switch-off-icon`: Material Symbols glyph name shown when the switch is unchecked.
- `data-switch-on-icon`: Material Symbols glyph name shown when the switch is checked.

Both icon-name attributes should be present when using `data-switch-icons`. If either one is missing, that state has no visible track icon.

## Behavior

Covered by [Playwright behavior tests](../../tests/e2e/forms-inputs.spec.js).

- SWT-001: The control uses native checkbox state, form submission, keyboard interaction, and disabled behavior.
- SWT-002: The switch styling only applies to checkbox inputs with `role="switch"`.
- SWT-003: The track shows `Off` when unchecked and `On` when checked.
- SWT-004: Switches with `data-switch-icons` replace the track text with the configured off and on icons.
- SWT-005: Checked switches use the shared primary token for the active track.
- SWT-006: Disabled switches dim through shared disabled surface and text tokens.
- SWT-007: Focus must remain clearly visible for keyboard users.
## Accessibility

- Use `type="checkbox"` with `role="switch"` for the input.
- Wrap the input in a native `<label>` or associate it with a label using `for` and `id`.
- Use concise label text that describes the setting being toggled.
- Treat track icons as decorative; the visible label still needs to describe the setting.
- Do not use a switch for multi-select lists; use the checkbox component instead.
- If helper or error text is needed, place it near the control and associate it with `aria-describedby`.

## Variables

| Variable | Type | Description |
| --- | --- | --- |
| `--switch-color-accent` | `<color>` | Sets --switch-color-accent so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--switch-color-border` | `<color>` | Sets --switch-color-border so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--switch-color-border-strong` | `<color>` | Sets --switch-color-border-strong so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--switch-color-border-subtle` | `<color>` | Sets --switch-color-border-subtle so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--switch-color-focus-ring` | `<color>` | Sets --switch-color-focus-ring so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--switch-color-primary` | `<color>` | Sets --switch-color-primary so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--switch-color-text` | `<color>` | Sets --switch-color-text so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--switch-color-text-inverse` | `<color>` | Sets --switch-color-text-inverse so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--switch-color-text-subtle` | `<color>` | Sets --switch-color-text-subtle so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--switch-control-border-width` | `<length>` | Sets --switch-control-border-width so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--switch-focus-ring-size` | `<length>` | Sets --switch-focus-ring-size so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--switch-font-family-sans` | `Any` | Sets --switch-font-family-sans so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--switch-font-size` | `<length>` | Sets --switch-font-size so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--switch-font-size-caption` | `<length>` | Sets --switch-font-size-caption so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--switch-font-weight-body-regular` | `<number>` | Sets --switch-font-weight-body-regular so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--switch-icon-fill` | `<number>` | Sets --switch-icon-fill so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--switch-icon-font-family` | `Any` | Sets --switch-icon-font-family so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--switch-icon-grad` | `<number>` | Sets --switch-icon-grad so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--switch-icon-opsz` | `<number>` | Sets --switch-icon-opsz so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--switch-icon-wght` | `<number>` | Sets --switch-icon-wght so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--switch-line-height` | `<number>` | Sets --switch-line-height so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--switch-space-inline` | `<length>` | Sets --switch-space-inline so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--switch-thumb-size` | `<length>` | Sets the switch thumb diameter and checked-state travel distance; change it with track height to preserve alignment. |
| `--switch-track-background` | `<color>` | Sets the switch track fill for off, on, focus, and disabled states; change it when switch state colors need a different semantic treatment. |
| `--switch-track-height` | `<length>` | Sets the switch track height and influences thumb sizing and vertical alignment; change it to tune control density. |
| `--switch-track-width` | `<length>` | Sets the switch track width and available thumb travel; change it when the switch should look more compact or more spacious. |

## Depends On

- `--color-accent`
- `--color-accent-disabled`
- `--color-border`
- `--color-border-strong`
- `--color-border-subtle`
- `--color-focus-ring`
- `--color-primary`
- `--color-text`
- `--color-text-inverse`
- `--color-text-subtle`
- `--font-family-sans`
- `--font-line-height-body`
- `--font-size`
- `--font-size-caption`
- `--font-weight-body-regular`
- `--icon-fill`
- `--icon-font-family`
- `--icon-grad`
- `--icon-opsz`
- `--icon-wght`
- `--layout-control-border-width`
- `--layout-control-min-height`
- `--layout-focus-ring-size`
- `--layout-space-inline`
