Switch
StableTurns a setting on or off with immediate effect, like a light switch. No save button needed.
When to use
Use it for
- Settings that apply as soon as they are flipped: notifications, auto-publish, preview mode.
- labelPlacement start in settings lists, so labels align left and switches align right.
Not for
- A choice saved later with a form button: use Checkbox.
- More than two states: use RadioGroup or Select.
- Starting an action (Publish, Sync): use Button.
Do and don't
Every example is rendered with the real component, so it always matches what ships.
Name the setting, not the state
The switch shows on or off; the label says what is on or off.
Labels that change with the state
"On" and "Off" labels repeat what the control already shows and hide what it controls.
A switch that waits for Save
Users expect a switch to act at once. Inside a form that saves later, use a Checkbox.
Accessibility
- Base UI Switch: role switch with aria-checked; Space and Enter toggle it; the label row is the click target.
- The off track uses control.track (3:1 against surfaces) and the thumb keeps 3:1 against the track, so the state is visible without color.
- The thumb position carries the state, not only the track color.
- If flipping it fails (network), revert it and say why next to it.
Anatomy and tokens
Read from packages/react/src/components/Switch/Switch.module.css at build time. Every value is a token: open one to see its
alias chain in both themes.
- Label row (click target)
.item - Size sm
.sm - Track
.track - Track
.track[data-checked] - Label row (click target), hover
@media (hover: hover) .item:hover .track[data-unchecked]:not([data-disabled]) - Label row (click target), hover
@media (hover: hover) .item:hover .track[data-checked]:not([data-disabled]) - Track, focus
.track:focus-visible - Thumb
.thumb - Thumb
.thumb[data-checked] - text
.text - Description
.description - Label row (click target)
.item:has([data-disabled]) - Label row (click target)
.item:has([data-disabled]) .description - Track
.track[data-disabled] - Track
.track[data-disabled][data-checked]
Props
Parsed from the TypeScript types in packages/react/src/components/Switch/Switch.tsx, so this table cannot drift from the
code.
| Prop | Type | Default | Description |
|---|---|---|---|
label required | ReactNode | none | Visible label. Name the setting, not the state: "Email notifications", not "On". |
description | ReactNode | none | Secondary text under the label, linked with aria-describedby. |
checked | boolean | none | No description in the code yet. |
defaultChecked | boolean | none | No description in the code yet. |
onCheckedChange | (checked: boolean) => void | none | No description in the code yet. |
labelPlacement | 'end' | 'start' | 'end' | `end` puts the label after the switch; `start` puts it first and pushes the switch to the row end (settings lists). Default `end`. |
size | 'sm' | 'md' | 'md' | Default `md` (36 by 20). `sm` (28 by 16) for dense tables. |
name | string | none | No description in the code yet. |
value | string | none | No description in the code yet. |
disabled | boolean | none | No description in the code yet. |
readOnly | boolean | none | No description in the code yet. |
required | boolean | none | No description in the code yet. |
id | string | none | No description in the code yet. |
className | string | none | No description in the code yet. |
Playground
Change the props and see the real Switch update. Controls are generated from the TypeScript props; nothing here changes the system.
<Switch defaultChecked label="Auto-publish approved tokens" />Workbench
For contributors: every state with the accessibility panel, in the component workbench (Storybook). The stories double as visual test fixtures; the guidance on this page is the user documentation (open Switch in Storybook) .
Embed Storybook stories here (5)
Loads from https://bridge-storybook.floriangouloubi.com (set STORYBOOK_URL at build time). If Storybook is not running, the frames stay
empty.
Default
On
WithDescription
SettingsRow
AllStates
Changelog
- New
Forms: Field (label, description, error wired by Base UI Field) and Input rebuilt on it (prefix, suffix, sizes; label, hint and error props kept). New Textarea (autosize, character count), Select (groups, descriptions), Combobox (filtering, async loading and empty states, multiple with chips), Checkbox (indeterminate, parent), CheckboxGroup, RadioGroup, Switch, Slider (single and range), NumberField (steppers, units) and Form (server errors with a focusable error summary, FormActions footer).
Unreleased (current version 0.1.0, no release tagged yet) , Oct 17, 2026
- New
Bridge token system v1. Adds a brand mapping layer (`bridge` default, `ocean` alternate) between primitives and semantic tokens, a component tier (button, input, checkbox, switch, slider, card, popup, dialog, tooltip, toast, table, tabs, progress, nav), comfortable and compact density, motion durations and easings with a reduced-motion override, layers (z-index), icon sizes, breakpoints, a 1.2 type scale from 14px with tracking tokens, and self-hosted IBM Plex Sans and Mono (`@bridge-ds/tokens/fonts.css`). Primitives are regenerated in OKLCH on one lightness ladder. The build now writes `dist/resolved.json` and fails when any pair in `contrast.checks.json` drops below its WCAG minimum in any brand and theme. Fixes `color.border.strong` against `color.surface.default` (now at least 3:1 in both themes).
Unreleased (current version 0.1.0, no release tagged yet) , Oct 17, 2026
- Fix
Library foundation pages (Color, Typography, Spacing, Radius and borders, Elevation) open each token group with a specimen of the real tokens in context, light and dark side by side, then a light list: dual swatch, the token name once, a one-line role, a muted alias line and a neutral usage chip. A page-level "Copy as" switch (CSS, JS, Figma) sets what a click on a name copies, and a row opens the token explorer's detail panel in read mode. Usage comes from the shared `tokenUsage()` definition, so the page background no longer reads as unused. Links in the app chrome are ink with a quiet underline; orange stays the signal for focus and the current place.
Unreleased (current version 0.1.0, no release tagged yet) , Oct 17, 2026