Switch

Switch

A toggle for switching a setting on or off, built on Base UI. Three sizes, with a thumb that stretches while pressed.

Playground

size
checked
disabled
<Switch defaultChecked />

Preview

Uncontrolled by default – set the initial state with defaultChecked, or control it with checked and onCheckedChange.

<Switch />
<Switch defaultChecked />

Installation

npx shadcn@latest add https://espresso-base-ui.vercel.app/r/switch.json

Usage

import { Switch } from "@/components/ui/switch"
<Switch
  defaultChecked
  onCheckedChange={(checked) => console.log(checked)}
/>

Sizes

Three sizes: xs (24×14), sm (26×16) and default (32×20). The thumb scales with the track.

<Switch size="xs" defaultChecked />
<Switch size="sm" defaultChecked />
<Switch size="default" defaultChecked />

Disabled

disabled mutes the track to bg-muted and blocks pointer events in both states.

<Switch disabled />
<Switch disabled defaultChecked />

Invalid

Set data-invalid to show the destructive validation treatment – a red border with a soft red ring. The same styles also activate automatically inside a Field marked invalid via group-data-[invalid=true]/field.

<Switch data-invalid="true" />
<Switch data-invalid="true" defaultChecked />

API reference

Switch composes the Base UI Root and Thumb parts, so it accepts every Base UI Switch.Root prop – checked, defaultChecked, onCheckedChange, disabled, required, readOnly, name and value for forms – plus the ones below.

Switch

PropTypeDefaultDescription
size"xs" | "sm" | "default""default"Track and thumb size: xs 24×14 with a 10px thumb, sm 26×16 with a 12px thumb, default 32×20 with a 14px thumb.
checkedboolean–Controlled on/off state; pair with onCheckedChange.
defaultCheckedbooleanfalseInitial state when uncontrolled.
onCheckedChange(checked, event) => void–Called with the next state on every toggle.
disabledbooleanfalsePrevents interaction and renders the muted track style.
data-invalidstring–Marks the control invalid: destructive border plus a destructive/20 ring. Typically "true".

Accessibility & styling hooks

The root renders a button with role="switch" and aria-checked, toggled with click, Space or Enter, and a hidden input keeps it form-compatible. An enlarged invisible hit area (after:-inset-x-3 after:-inset-y-2) makes the small control easy to tap. The root exposes data-slot="switch" and the thumb data-slot="switch-thumb"; both reflect state as data-checked / data-unchecked, and the root additionally carries data-size, data-disabled and data-invalid for CSS targeting. The switchVariants cva helper is exported for building custom switch-shaped controls.

Search documentation

Search the component docs