Switch
Accessible toggle switch with controlled/uncontrolled support and form integration.
Switch
The Switch component is a fully accessible toggle switch (also called a checkbox switch). It supports controlled and uncontrolled modes, works in forms, and has proper ARIA semantics. Use it for binary on/off settings.
Switch is unstyled. Use SwitchThumb to render the visual toggle indicator inside Switch.
Features
- Controlled/uncontrolled modes
- Form integration (works with form submission)
- Optional SwitchThumb for visual indicator
- ARIA switch semantics (
role="switch",aria-checked) - Keyboard support (Space to toggle)
- Disabled state support
Usage
import { Switch, SwitchThumb } from '@loke/ui/switch';
export default function Example() {
const [checked, setChecked] = React.useState(false);
return (
<div className="flex items-center gap-2">
<Switch checked={checked} onCheckedChange={setChecked}>
<SwitchThumb className="w-6 h-6 bg-gray-400 rounded-full transition-transform" />
</Switch>
<label>{checked ? 'On' : 'Off'}</label>
</div>
);
}Props
Switch
Prop
Type
SwitchThumb
Prop
Type
Examples
Off
Notifications are disabled
Basic toggle
<Switch defaultChecked>
<SwitchThumb className="w-5 h-5 bg-white rounded-full shadow transition-transform group-data-[state=checked]:translate-x-5" />
</Switch>With label
<div className="flex items-center gap-3">
<Switch id="notifications" defaultChecked>
<SwitchThumb className="w-6 h-6 bg-gray-400 rounded-full" />
</Switch>
<label htmlFor="notifications">Enable notifications</label>
</div>In a form
<form onSubmit={handleSubmit}>
<label>
<Switch name="marketing-emails" defaultChecked>
<SwitchThumb className="w-5 h-5 bg-gray-400 rounded-full" />
</Switch>
Send me marketing emails
</label>
<button type="submit">Save</button>
</form>Styled with Tailwind
<Switch defaultChecked>
<SwitchThumb
className={`
inline-block w-5 h-5 rounded-full
transition-all duration-200 ease-out
data-[state=unchecked]:bg-gray-300
data-[state=checked]:bg-green-600
`}
/>
</Switch>Keyboard Navigation
- Space: Toggle the switch
- Tab: Move focus to the switch
- Shift+Tab: Move focus away from the switch
Accessibility
- Switch has
role="switch"andaria-checked="true|false" - Disabled switches have
aria-disabled="true" - Labels should use
htmlForto associate with Switch's ID SwitchThumbhasdata-state="checked|unchecked"for styling based on state
Form Integration
Switch can be used directly in forms:
<form>
<Switch name="terms" required>
<SwitchThumb />
</Switch>
<button type="submit">Agree and sign up</button>
</form>The switch will submit its value (default "on") when checked, or no value when unchecked.
Best practices
- Always provide a label (either via
<label htmlFor>oraria-label) - Style SwitchThumb with
data-[state=checked]anddata-[state=unchecked]selectors - Keep the switch itself small and the clickable area reasonable (40–44px minimum)
- Use disabled state sparingly; explain why the switch is disabled if unclear
- Test with keyboard navigation (Space key) to ensure toggle works