Switch
A switch with weight: the thumb stretches on press, is thrown across with a slight overshoot, and spins while an async save settles.
Used forSettings pagesFeature flagsTable rowsPricing
Install with the shadcn CLI
Templates
Need the whole page?
43 Next.js landing pages, each designed from scratch. Try any of them live; one is $39, all of them $99, and 5 are free.
Where it’s used
Settings pages
Notification and privacy toggles that save as you flip them.
Feature flags
Turning a flag on in an admin panel with the request in flight.
Table rows
An Active column you can flip inline.
Pricing
A compact on/off beside an option.
What it handles for you
An optimistic toggle needs pending state, rollback and an error signal, and most switches leave all three to you.
Async without wiring
Return a promise from onCheckedChange: pending spinner, then settled or thrown back.
Weight in the motion
The thumb stretches 4px on press and is thrown with an overshoot (420ms).
role="switch"
aria-checked and aria-busy, Space and Enter.
Label either side
labelPosition="start" for settings rows with the switch on the right.
Overview
Settings switches usually flip instantly and lie when the save fails. This one flips at once, spins in its thumb while your promise runs, and throws itself back with a small shake if it rejects. Pressing stretches the thumb toward where it will go, and the track fills in step.
States
- off / on
- The thumb is thrown across (420ms, slight overshoot) and the primary fill fades in (260ms).
- press
- The thumb stretches 4px toward its next side.
- pending
- The thumb shows a spinner; the switch ignores presses.
- failed
- The thumb is thrown back and the track shakes (320ms).
Usage
Props
| Prop | Type | Description |
|---|---|---|
| checked / defaultChecked | boolean | State. |
| onCheckedChange | (checked) => void | Promise | Return a promise for the pending thumb; reject to put it back. |
| label / description | ReactNode | Text beside the switch. |
| labelPosition | "start" | "end"default "end" | Label before or after. |
| size | "sm" | "md"default "md" | 16px or 20px tall. |
Accessibility and motion
- Reduced motion: the thumb moves at once and nothing shakes.
- While pending, aria-busy is set and further presses are ignored.
Requirements
React 19, Tailwind CSS v4 and shadcn/ui theme variables (any style, light and dark). Icons from lucide-react.
The CLI also installs ui-interaction-motion.
Source
Registry item: /r/switch.json


