Duck Switch
The duck entering the water: the track floods lime and one ripple spreads from the entry point.
InputsClient component
Preview
Installation
The CLI writes the source into your project and pulls in whatever it depends on.
$
pnpm dlx shadcn@latest add @duck/duck-switchPulls in @duck/theme. Already installed items are skipped.
Usage
import { DuckSwitch } from "@/components/ui/duck-switch"The file lands in components/ui/duck-switch.tsx and belongs to you from that point on. Edit it in place rather than wrapping it.
Props
Everything not listed here is forwarded to the underlying element.
| Prop | Type | Default | Description |
|---|---|---|---|
| size | sm | default | default | Track size. Both keep a tap target of at least 24px. |
| children | ReactNode | - | Visible label, rendered inside the <label>. Without one, pass an aria-label. |
| checked / defaultChecked / onChange | native | - | It is an <input type="checkbox">, so controlled and uncontrolled both work and it submits with the form. |
Rules
What keeps this component from turning into noise.
- The off state is drawn by the 3px border, never by the fill — a muted fill on a card is about 1.2:1 and disappears.
- Knob travel is longer than the knob is wide, so the state survives without colour.
- Space toggles natively. Enter is wired up too, per the ARIA switch pattern.
