Switch

A toggle control for switching between on and off states.

Installation

bash
npx @smicolon/cli add switch

Run init once per project before adding components. See Installation.

Preview

Variants

Two styles, as in Figma. solid, the default, fills the track, with the primary colour when on. outline keeps the track on the page background, draws it with a 1px line, and fills the thumb instead.

solid
outline

Sizes

Three sizes. md is the default. The track is 32, 40 or 48px wide, and the label stays the same size.

solid
outline

Layout

control-first, the default, puts the track before the label and lines the description up under the label. label-first puts the label at the start and the track at the end of a full-width row, for settings lists.

control-first
label-first

States

Focus is a real CSS state rather than a prop. Tab to a switch to see the ring. Disabled dims the whole switch, label and description included.

solid
outline

Accessibility

  • Renders a native <input type="checkbox" role="switch">, so Space toggles it and it submits with a form without extra code.
  • description is linked with aria-describedby; the track is hidden from assistive technology.
  • Without a label, pass an aria-label.
  • Direction is inherited from dir, never a prop. The thumb always moves towards the end of the line when the switch turns on.

Props

PropTypeDefaultDescription
variant"solid" | "outline""solid"A filled track or an outlined one.
layout"control-first" | "label-first""control-first"Track before the label, or after it.
size"sm" | "md" | "lg""md"Switch size.
checkedboolean—On state. Use it with onChange.
defaultCheckedbooleanfalseStarting state when you do not control it.
disabledbooleanfalseDisables the switch and dims it.
labelstring—Label text.
descriptionstring—Secondary line below the label.
namestring—Name submitted with the form.
onChange(event) => void—Called when the switch changes.
classNamestring—Extra classes for the component.

Usage

tsx
import { Switch } from "@/components/ui/switch"

// Basic switch
<Switch aria-label="Airplane mode" />

// With label
<Switch label="Airplane mode" defaultChecked />

// With description
<Switch
  label="Dark mode"
  description="Toggle dark mode on or off"
/>

// Outline style
<Switch variant="outline" label="Auto-sync" />

// Label first, track at the end
<Switch layout="label-first" label="Notifications" />

// Different sizes
<Switch size="sm" label="Small" />
<Switch size="md" label="Medium" />
<Switch size="lg" label="Large" />

// Controlled
const [enabled, setEnabled] = useState(true)

<Switch
  label="Notifications"
  checked={enabled}
  onChange={(e) => setEnabled(e.target.checked)}
/>

State: On