Skip to the content
BooleanPress UI

Form

Switch

Turns one setting on or off, and takes effect as soon as it is flipped.

Import

import { Switch } from "@booleanpress/ui/switch"

Usage

Give every switch a visible name: a Label whose htmlFor is the switch's id. Clicking the label flips it.

import { Label } from "@booleanpress/ui/label"
import { Switch } from "@booleanpress/ui/switch"

export function LogSetting() {
  return (
    <div className="flex items-center gap-2">
      <Switch id="log-emails" defaultChecked />
      <Label htmlFor="log-emails">Keep the email log</Label>
    </div>
  )
}

It is uncontrolled with defaultChecked, or controlled with checked and onCheckedChange. size is default or sm. Use a switch for a setting that applies at once; use a Checkbox for a choice that is submitted with a form or that belongs to a list of options.

Examples

Basic

Off and on, each named by its label.

Controlled

checked and onCheckedChange keep the setting in your state, here shown beneath the switch.

Sizes

default is 32 × 18 px; sm is 24 × 14 px, for dense rows.

Disabled

A disabled switch keeps its state, ignores clicks and keys, and leaves the tab order.

Invalid

aria-invalid and aria-describedby tell assistive technology about the error; the switch draws no error border, so show the message as text.

Accessibility

Semantics
A button with role="switch" and aria-checked (true or false); the thumb is decorative. Inside a form, it also renders a hidden native checkbox, so the value is submitted with the form.
Labels
Name every switch: a Label with htmlFor, or aria-label when no visible text fits. Word the label for the "on" state ("Keep the email log"), because a screen reader adds "on" or "off" itself.
Focus
It is in the tab order. The focus ring shows on keyboard focus, not on click.
Known limits
  • The default track is 18 px high and the small one 14 px. Keep the label beside the switch, so the label adds to the target and the pair meets WCAG 2.5.8's 24 px.
  • Unlike the other form controls, the switch has no error border for aria-invalid; the visible error message is the only sign for sighted people.

Keyboard

Keyboard
KeyBehaviour
SpaceFlips the switch.
EnterFlips the switch. APG lists Enter as optional.

API

Switch

Renders Radix Switch.Root and passes it every other prop.

Switch props
PropTypeDefaultDescription
asChildbooleanRender the child element instead, with this part's behaviour and classes merged onto it.
checkedbooleanThe state, when you control it. Pair it with onCheckedChange.
defaultCheckedbooleanThe state it starts in, when it controls itself.
onCheckedChange((checked: boolean) => void)Called with the new state when it is flipped.
requiredbooleanThe form cannot be submitted until it is on.
size"default" | "sm"defaultdefault or sm.

Every part takes className, merged with its defaults by cn(), and ref, which reaches the element it renders.

Data attributes: data-slot="switch" (Switch), and data-size.

Theming

The track is --primary when on and --control when off, at least 3:1 against the surface; the thumb is --background. The thumb slides toward the end of the line, so it mirrors in right-to-left.

The tokens its classes read. Change their values in your theme, and it follows.

Theme tokens
TokenUsed for
--backgroundbackground
--controlbackground
--foregroundbackground
--inputbackground
--primarybackground
--primary-foregroundbackground
--ringborder, focus ring