Skip to content
Primitives

Switch

Sharp toggle switch; signal fill when on.

● LIVE
npx shadcn@latest add https://okibi.cndr.dev/r/switch.json

Installation

Install the theme first, then add the component:

npx shadcn@latest add https://okibi.cndr.dev/r/switch.json

Install the required dependencies:

npm install @radix-ui/react-switch

Copy the source from the Code tab above into components/ui/switch.tsx. It uses the cn helper and the okibi theme tokens — install the theme first if you haven't.

Usage

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

<Switch id="ice" defaultChecked />

Anatomy

<Label htmlFor="ice">Ice protection</Label>
<Switch id="ice" defaultChecked />   {/* single Radix Switch.Root + Thumb */}

Examples

Disabled

The native disabled attribute locks the toggle in its current on/off state.

● LIVE

API Reference

Switch

PropTypeDefaultDescription
checkedbooleanControlled on/off state.
defaultCheckedbooleanfalseInitial state when uncontrolled.
onCheckedChange(checked: boolean) => voidFires when the switch is toggled.
disabledbooleanfalseLock the switch and drop it to opacity-60.
requiredbooleanfalseMark the control required inside a form.
namestringField name submitted with the surrounding form.

Accessibility

  • Built on Radix Switch.Root, exposing role='switch' with aria-checked toggled by Space / Enter.
  • On / off is reflected via data-state driving the track color and the thumb's translate-x.
  • aria-invalid='true' flips the track to the destructive keyline (border-destructive, ring-destructive).
  • Focus shows the 2px signal ring (focus-visible:ring-2 ring-ring ring-offset-2).
  • The control is 20x36px — below the 44px touch minimum — so always pair it with a clickable Label to extend the target.
  • Disabled is disabled:opacity-60 with pointer events off; the thumb slide uses the fast token, no spring.

Guidelines

Do

  • Use a switch for an instant on/off setting that takes effect immediately, with no Save step.
  • Always pair with a Label (via htmlFor / id) to name the control and widen the tap target.
  • Drive it controlled with checked + onCheckedChange when the value lives in app state.

Don't

  • Don't use a switch where the change only applies after submitting a form — use a Checkbox.
  • Don't leave the switch unlabeled; an icon alone is not an accessible name.
  • Don't stack many switches without labels in a tight row — they fall below the touch target.

On this page