StartFoundationsComponentsContent

Switch

A switch turns one setting on or off, and the change applies at once. There is no Save step.

Stable Figma
OverviewUsageAPIAccessibility
Auto-enhance photos
<tk-switch checked helper="Applies to all new uploads">Auto-enhance photos</tk-switch>

Anatomy

Part What it is
tk-switch the element; one Tab stop
default slot the label, before the track, required; it is the accessible name and can hold a link
helper an optional hint under the label
track the pill; accent when on, gray when off
thumb the white pill that moves to the on or off side
✓ and ✕ marks inside the track; with the thumb position, they show the state without color
spinner beside the track while loading

The whole row, label and track, is one click target. A long label wraps, and the track stays level with its first line. In right-to-left layouts everything mirrors.

Sizes

Show previews Compact rows
<tk-switch>Show previews</tk-switch>
<tk-switch size="small">Compact rows</tk-switch>
size Track Thumb
medium (default) 40 × 20px 20 × 16px
small 32 × 16px 16 × 12px

Both rows are at least 24px tall. Use small only in dense lists of settings. The label and helper don't change size.

States

Wi-Fi Essential cookies Sync over cellular
<tk-switch checked>Wi-Fi</tk-switch>
<tk-switch checked disabled>Essential cookies</tk-switch>
<tk-switch loading>Sync over cellular</tk-switch>

On hover, the track changes shade. Keyboard focus shows a ring around the track.

  • checked: the initial state. A click toggles it; read the live state from the checked property.
  • disabled: can't be focused or changed. Use it for settings that must stay on, or rows turned off by a parent setting. A disabled track is gray whether on or off, and in dark the two are the same color, so the thumb and the ✓ or ✕ show the state.
  • loading: the switch keeps its current state, ignores input, and stays focusable. A spinner shows beside it, and screen readers hear "Loading" if the wait passes 2 seconds.

There is no error state. If a save fails, leave the switch as it was and say what happened elsewhere, such as in a Toast.

Saving to a server

To flip only after a save succeeds, cancel the click, show loading, and set checked yourself:

<tk-switch id="sync">Sync over cellular</tk-switch>
<script>
  const sync = document.querySelector('#sync');
  sync.addEventListener('click', async (e) => {
    e.preventDefault();
    sync.loading = true;
    const next = !sync.checked;
    if (await save(next)) sync.checked = next;
    sync.loading = false;
  });
</script>

Without a listener, the switch flips at once, which suits settings kept on the device.

Settings lists

Stack switches as your own layout; each one stands alone. Past about 5 rows, add section headings. If one switch controls the others, set disabled on the dependent rows while it's off. With label-hidden, the label still has to name the setting.