Switch
A toggle switch component for binary choices, built on Base UI primitives with comprehensive accessibility and dark mode support.
Features
- Accessible: Built with proper ARIA attributes and keyboard navigation
- Customizable: Multiple sizes and composable components
- Form Integration: Works seamlessly with form libraries
- Dark Mode: Full support for light and dark themes
- TypeScript: Fully typed with excellent IntelliSense
Installation
The Switch component is included in the @bao-ui/react package.
Basic Usage
import { Switch } from '@bao-ui/react'
export function BasicSwitch() {
return <Switch label="Enable notifications" />
}With Description
<Switch
label="Marketing emails"
description="Receive emails about new products and features."
/>Sizes
<Switch size="sm" label="Small switch" />
<Switch size="default" label="Default switch" />
<Switch size="lg" label="Large switch" />States
<Switch label="Default" />
<Switch label="Checked" defaultChecked />
<Switch label="Disabled" disabled />
<Switch label="Disabled & Checked" disabled defaultChecked />Controlled
import { useState } from 'react'
import { Switch } from '@bao-ui/react'
export function ControlledExample() {
const [checked, setChecked] = useState(false)
return (
<div className="space-y-4">
<Switch
label="Controlled switch"
checked={checked}
onCheckedChange={setChecked}
/>
<div className="text-sm text-muted-foreground">
Current state: {checked ? 'On' : 'Off'}
</div>
</div>
)
}Settings Panel Example
Custom Composition
For advanced use cases, you can compose the switch using individual components:
import {
SwitchRoot,
SwitchThumb,
SwitchFieldRoot,
SwitchLabel,
SwitchDescription,
} from '@bao-ui/react'
;<SwitchFieldRoot>
<div className="flex items-center justify-between">
<div>
<SwitchLabel>Custom layout switch</SwitchLabel>
<SwitchDescription>
This uses individual components for maximum flexibility.
</SwitchDescription>
</div>
<SwitchRoot defaultChecked>
<SwitchThumb />
</SwitchRoot>
</div>
</SwitchFieldRoot>API Reference
Switch
The main switch component that combines all sub-components for convenience.
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | - | Label text for the switch |
description | string | - | Helper text below the switch |
size | 'sm' | 'default' | 'lg' | 'default' | Size of the switch |
checked | boolean | - | Controlled checked state |
defaultChecked | boolean | false | Default checked state |
onCheckedChange | (checked: boolean) => void | - | Callback when checked state changes |
disabled | boolean | false | Whether the switch is disabled |
id | string | - | HTML id attribute |
className | string | - | Additional CSS classes |
SwitchRoot
The root switch element.
| Prop | Type | Default | Description |
|---|---|---|---|
size | 'sm' | 'default' | 'lg' | 'default' | Size of the switch |
checked | boolean | - | Controlled checked state |
defaultChecked | boolean | false | Default checked state |
onCheckedChange | (checked: boolean) => void | - | Callback when checked state changes |
disabled | boolean | false | Whether the switch is disabled |
className | string | - | Additional CSS classes |
SwitchThumb
The movable thumb element.
| Prop | Type | Default | Description |
|---|---|---|---|
size | 'sm' | 'default' | 'lg' | 'default' | Size of the thumb |
className | string | - | Additional CSS classes |
SwitchFieldRoot
Wrapper component for field integration.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes |
SwitchLabel
Label component for the switch.
| Prop | Type | Default | Description |
|---|---|---|---|
htmlFor | string | - | Associates label with switch |
className | string | - | Additional CSS classes |
SwitchDescription
Description text component.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes |
Accessibility
The Switch component follows WAI-ARIA guidelines:
- Uses proper ARIA attributes (
role="switch",aria-checked) - Supports keyboard navigation (Space/Enter to toggle)
- Provides proper focus management
- Associates labels with the switch control
- Announces state changes to screen readers
Examples
Form Integration
import { useState } from 'react'
import { Switch } from '@bao-ui/react'
export function SettingsForm() {
const [settings, setSettings] = useState({
notifications: false,
marketing: true,
})
const handleSubmit = e => {
e.preventDefault()
console.log('Settings:', settings)
}
return (
<form onSubmit={handleSubmit} className="space-y-4">
<Switch
label="Email Notifications"
description="Receive email updates"
checked={settings.notifications}
onCheckedChange={checked =>
setSettings(prev => ({ ...prev, notifications: checked }))
}
/>
<Switch
label="Marketing Emails"
description="Receive promotional content"
checked={settings.marketing}
onCheckedChange={checked =>
setSettings(prev => ({ ...prev, marketing: checked }))
}
/>
<button type="submit">Save Settings</button>
</form>
)
}Without Label
// For inline controls where context is provided elsewhere
<div className="flex items-center space-x-2">
<span>Dark Mode</span>
<Switch />
</div>