Switch
A labelled boolean toggle. The caption beside it changes with the state, so the current setting is readable as words rather than inferred from a knob.
'use client'
import * as React from 'react'
import { Switch } from '@/components/custom/switch'
export default function SwitchDemo() {
const [carryOver, setCarryOver] = React.useState(true)
const [notify, setNotify] = React.useState(false)
return (
<div className="w-full max-w-sm space-y-2">
<Switch label="Carry over unused leave" checked={carryOver} onCheckedChange={setCarryOver} />
<Switch
label="Email the approver"
checked={notify}
onCheckedChange={setNotify}
trueLabel="Send an email"
falseLabel="Do not send an email"
/>
</div>
)
}Installation
pnpm dlx shadcn@latest add https://kiotapay-ui-staging.staging.kiotapay.com/r/switch.jsonnpx shadcn@latest add https://kiotapay-ui-staging.staging.kiotapay.com/r/switch.jsonyarn dlx shadcn@latest add https://kiotapay-ui-staging.staging.kiotapay.com/r/switch.jsonbunx --bun shadcn@latest add https://kiotapay-ui-staging.staging.kiotapay.com/r/switch.jsonInstalls components/custom/switch.tsx, the shadcn switch primitive and form-field. The bare primitive stays at @/components/ui/switch.
Usage
'use client'
import { Switch } from '@/components/custom/switch'
export function CarryOverField({ value, onChange }) {
return (
<Switch
label="Carry over unused leave"
checked={value}
onCheckedChange={onChange}
trueLabel="Carries over"
falseLabel="Expires at year end"
/>
)
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | — | Required. Rendered above the switch. |
checked | boolean | false | Controlled state. |
onCheckedChange | (checked: boolean) => void | — | Fires on toggle. |
description | string | — | Fixed caption. Overrides both state labels. |
trueLabel | string | 'Yes' | Caption while on. |
falseLabel | string | 'No' | Caption while off. |
disabled | boolean | false | Blocks toggling. |
error | boolean | false | Turns the label to the danger ramp. |
errorMessage | ReactNode | — | Shown only while error is true. |
Behaviour notes
Say what the state means, not just yes or no. trueLabel/falseLabel default to Yes and No, but a switch reads far better when the caption states the consequence — "Carries over" beats "Yes" for anyone arriving at the form cold.
The caption is a <label> for the switch, so clicking the words toggles it. That is a much larger target than the switch itself.