Installation
pnpm dlx shadcn@latest add https://rdf.dev.360online.com/r/switch.jsonInstalls to @/components/ui/switch.
Manual installation
Install the dependencies:
pnpm add @base-ui/react@^1.8.0Copy the source into your project:
'use client'
import { Switch as SwitchPrimitive } from '@base-ui/react/switch'
import { cn } from '@/lib/utils'
function Switch({
className,
size = 'default',
...props
}: SwitchPrimitive.Root.Props & {
size?: 'sm' | 'default'
}) {
return (
<SwitchPrimitive.Root
data-slot="switch"
data-size={size}
className={cn(
'peer group/switch relative inline-flex shrink-0 cursor-pointer items-center rounded-full border border-transparent transition-all outline-none group-has-[:focus-visible]/field-label:border-transparent group-has-[:focus-visible]/field-label:ring-0 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 p-0.5 data-[size=default]:h-5 data-[size=default]:w-9 data-[size=sm]:h-4 data-[size=sm]:w-7 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:bg-primary data-checked:hover:bg-primary/90 data-unchecked:border-input data-unchecked:bg-background data-unchecked:hover:border-primary/90 data-disabled:cursor-not-allowed data-disabled:opacity-50',
className,
)}
{...props}
>
<SwitchPrimitive.Thumb
data-slot="switch-thumb"
className="pointer-events-none block rounded-full ring-0 transition-transform group-data-[size=default]/switch:size-3.5 group-data-[size=sm]/switch:size-2.5 group-data-[size=default]/switch:data-checked:translate-x-4 group-data-[size=sm]/switch:data-checked:translate-x-3 data-checked:bg-background group-data-[size=default]/switch:data-unchecked:translate-x-0 group-data-[size=sm]/switch:data-unchecked:translate-x-0 data-unchecked:bg-foreground group-hover/switch:data-unchecked:bg-primary/90"
/>
</SwitchPrimitive.Root>
)
}
export { Switch }A switch component that allows users to toggle between two states (on/off). Built on top of Base UI Switch, it follows WAI-ARIA design patterns and is fully accessible.
Features
- Two sizes:
defaultandsm - Controlled (
checked/onCheckedChange) and uncontrolled (defaultChecked) modes - Disabled state
- Invalid state via
aria-invalid - Enlarged hit area for easier clicking
- Works with
Labelor theFieldcomponents, including selectable choice cards - Keyboard navigation and screen reader support
Usage
import { Switch } from '@/components/ui/switch'
import { Label } from '@/components/ui/label'
export function MyForm() {
return (
<div className="flex items-center gap-2">
<Switch id="airplane-mode" />
<Label htmlFor="airplane-mode">Airplane mode</Label>
</div>
)
}Size
<Switch size="sm" />
<Switch size="default" />With Field
import { Field, FieldContent, FieldDescription, FieldLabel } from '@/components/ui/field'
import { Switch } from '@/components/ui/switch'
<Field orientation="horizontal">
<FieldContent>
<FieldLabel htmlFor="share">Share across devices</FieldLabel>
<FieldDescription>Focus is shared across devices.</FieldDescription>
</FieldContent>
<Switch id="share" />
</Field>Examples
Default
Sizes
sm suits dense tables and toolbars; default suits forms and settings pages.
Horizontal
Several small switches in a row as quick filters above a case list.
Disabled State
Settings the resident can't change. Set data-disabled="true" on the Field to dim the label and description too.
Invalid
Set aria-invalid on the switch and data-invalid on the Field, and explain the problem with FieldError. Turn the switch on to clear the error.
With Description
A horizontal Field with the label and description on the left and the switch on the right.
Choice Card
Wrap a horizontal Field in a FieldLabel to make the whole card toggle the switch – here for home care services.
Settings
A notification settings card grouping switches with FieldGroup and FieldSeparator.
Accessibility
The Switch component follows WAI-ARIA guidelines for switches:
- Uses proper ARIA roles (
switch) - Supports keyboard navigation:
Tab: Move focus to the switchSpace: Toggle the switch state
- Provides proper labeling and descriptions
- Maintains focus management
- Includes visual focus indicators
- Supports screen reader announcements
Best Practices
- Always provide labels for switches
- Use clear, action-oriented labels
- Consider adding descriptions for complex toggles
- Use appropriate spacing between switch and label
- Provide clear visual feedback for state changes
- Consider using icons for additional visual clarity
- Use switches for binary choices (on/off, yes/no)
Related Components
- Checkbox
- Radio Group
- Toggle
- Field