Switch
A control that allows users to toggle between checked and not checked states. Perfect for settings, preferences, and feature toggles in React applications with Next.js, TypeScript, and Tailwind CSS.
You know those toggle switches that just feel right when you flip them? Like the ones on your phone for airplane mode or dark theme? That's what Switch gives you - a satisfying binary control that users actually want to interact with.
Basic toggle
Simple on/off control with proper labeling:
Just a clean toggle with clear labeling. This free open source React component handles all the accessibility requirements so screen readers know what's being toggled and users can navigate with keyboards.
npx shadcn@latest add switch
Why switches beat checkboxes for settings
Sometimes you need something that feels more immediate than a checkbox:
- Visual feedback - Users see the state change instantly
- Mobile friendly - Large touch targets that feel natural to tap
- Settings context - Clearly indicates system preferences vs form data
- Immediate effect - Perfect when changes apply right away
- Status indication - Shows current state at a glance
- Satisfying interaction - That little slide animation feels good
Real-world switch patterns
Form integration
Email preferences with proper validation:
Settings panel
App preferences grouped logically:
These examples show switches in their natural habitat - settings screens, preference panels, and feature toggles. Each switch clearly communicates what it controls and responds immediately.
Perfect for user preferences
Switches work best when the change takes effect immediately. Dark mode, notifications, privacy settings, feature flags, accessibility options. Much better than checkboxes when you're dealing with system-level toggles rather than form data.
Built on Radix UI Switch primitive with full keyboard navigation support. Full TypeScript support. Styled with Tailwind CSS to match the shadcn design system.
Radix UI Foundation
The Switch component is built on top of Radix UI's Switch primitive, providing:
- Full keyboard navigation - Space and Enter keys toggle the switch
- Accessibility compliance - Adheres to the switch ARIA role requirements
- Form integration - Renders a hidden input for proper form submission
- Controlled/uncontrolled - Works in both controlled and uncontrolled modes
- Data attributes - Provides
data-state
anddata-disabled
attributes for styling
Component Structure
The Radix UI Switch consists of two main parts:
import * as Switch from "@radix-ui/react-switch"
<Switch.Root>
<Switch.Thumb />
</Switch.Root>
API Reference
Switch (Root)
Contains all parts of the switch and renders a hidden input for forms.
Prop | Type | Default | Description |
---|---|---|---|
checked | boolean | - | The controlled checked state of the switch |
defaultChecked | boolean | - | The default checked state (uncontrolled) |
onCheckedChange | (checked: boolean) => void | - | Event handler called when the checked state changes |
disabled | boolean | false | Whether the switch is disabled |
required | boolean | false | Whether the switch is required in forms |
name | string | - | The name of the switch for form submission |
value | string | "on" | The value given as data when submitted with a name |
id | string | - | The id attribute for the switch |
className | string | - | Additional CSS classes |
Data Attributes
The switch automatically applies data attributes for styling:
Attribute | Values | Description |
---|---|---|
[data-state] | "checked" | "unchecked" | Indicates the current state |
[data-disabled] | Present when disabled | Applied when switch is disabled |
State management
The Switch can be controlled or uncontrolled:
// Controlled
const [enabled, setEnabled] = useState(false)
<Switch checked={enabled} onCheckedChange={setEnabled} />
// Uncontrolled
<Switch defaultChecked={true} />
Form integration
Works seamlessly with React Hook Form and other form libraries:
<FormField
control={form.control}
name="notifications"
render={({ field }) => (
<FormItem className="flex items-center justify-between">
<FormLabel>Push Notifications</FormLabel>
<FormControl>
<Switch
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
</FormItem>
)}
/>
Accessibility features
Built-in accessibility support includes:
- ARIA labels - Proper role and state attributes
- Keyboard support - Space and Enter keys toggle the switch
- Focus management - Clear visual focus indicators
- Screen reader support - State changes are announced
- Label association - Connects with Label components via id/htmlFor
- Form integration - Works with form validation and submission
Keyboard navigation
Key | Action |
---|---|
Space | Toggle the switch |
Enter | Toggle the switch |
Switch vs Checkbox guidelines
Use Switch when:
- Settings and preferences - System-level configuration
- Immediate effect - Change applies right away without form submission
- Binary states - Clear on/off, enabled/disabled states
- Feature toggles - Turning functionality on or off
Use Checkbox when:
- Form data - Part of form that gets submitted
- Multiple selection - Selecting items from a list
- Agreement - Terms acceptance, consent flows
- Data collection - Gathering user information
Design patterns for switches
Settings organization
Group related switches with clear section headers:
<div className="space-y-6">
<div>
<h3 className="mb-4 text-lg font-medium">Notifications</h3>
<div className="space-y-4">
<SwitchItem label="Email updates" />
<SwitchItem label="Push notifications" />
</div>
</div>
<div>
<h3 className="mb-4 text-lg font-medium">Privacy</h3>
<div className="space-y-4">
<SwitchItem label="Analytics" />
<SwitchItem label="Location sharing" />
</div>
</div>
</div>
Descriptive labels
Always include helpful descriptions for complex settings:
<div className="flex items-center justify-between">
<div className="space-y-0.5">
<Label className="font-medium">Auto Save</Label>
<p className="text-sm text-muted-foreground">
Automatically save your work as you type
</p>
</div>
<Switch />
</div>
Immediate feedback
Show the effect of toggle changes right away:
const [darkMode, setDarkMode] = useState(false)
useEffect(() => {
document.documentElement.classList.toggle('dark', darkMode)
}, [darkMode])
<Switch
checked={darkMode}
onCheckedChange={setDarkMode}
/>
Common switch scenarios
Keep these patterns in mind when adding switches to your interface:
- Label clearly - Describe exactly what the switch controls
- Group logically - Related settings should be visually connected
- Show current state - Make the on/off position obvious
- Provide descriptions - Explain what happens when toggled
- Test on mobile - Ensure touch targets are large enough
- Consider consequences - Some settings might need confirmation dialogs
- Persist state - Remember user preferences across sessions
- Handle errors gracefully - What if the setting change fails?
Sonner
An opinionated toast component for React. Perfect for notifications, confirmations, and user feedback in Next.js, TypeScript, and Tailwind CSS applications.
Table
A responsive table component for displaying tabular data. Perfect for dashboards, admin panels, and data management in React applications with Next.js, TypeScript, and Tailwind CSS.