Switch
The Switch component provides a toggle control for enabling or disabling features, with smooth animations and clear visual feedback for binary state changes.
Usage
import { Switch, SwitchGroup, SwitchSize } from 'blend-v1' function MyComponent() { const [isEnabled, setIsEnabled] = useState(false) return ( <Switch checked={isEnabled} onChange={setIsEnabled} label="Enable notifications" size={SwitchSize.MEDIUM} /> ) }
API Reference
Switch Props
Prop Name | Type |
---|---|
id | string |
checked | boolean |
defaultChecked | boolean |
onChange | (checked: boolean) => void |
disabled | boolean |
required | boolean |
error | boolean |
size | SwitchSize |
label | ReactNode |
subtext | ReactNode |
slot | ReactNode |
name | string |
value | string |
SwitchGroup Props
Prop Name | Type |
---|---|
id | string |
label | string |
name | string |
children | ReactNode |
disabled | boolean |
value | string[] |
defaultValue | string[] |
onChange | (value: string[]) => void |
Features
- Two size variants (small, medium)
- Switch group management with multiple selections
- Optional subtext for additional context
- Optional slot for badges, icons, or other elements
- Required field indicator (asterisk)
- Error state styling
- Disabled state support
- Controlled and uncontrolled modes
- Smooth animations and transitions
- Accessible by default
- Built on native HTML button elements
- Customizable styling through tokens
Usage Examples
Basic Switch
Simple switch with label
import { Switch } from 'blend-v1' function MyComponent() { const [isEnabled, setIsEnabled] = useState(false) return ( <Switch checked={isEnabled} onChange={setIsEnabled} label="Enable notifications" /> ) }
Switch with Subtext
Switch with additional descriptive text
<Switch checked={darkMode} onChange={setDarkMode} label="Dark mode" subtext="Use dark theme for better viewing in low light" />
Switch with Slot
Switch with additional elements (badges, icons, etc.)
<Switch checked={autoSave} onChange={setAutoSave} label="Auto save" slot={<span className="text-green-500 text-sm">Recommended</span>} />
Different Sizes
Switches with different size variants
// Small size <Switch checked={isEnabled} onChange={setIsEnabled} label="Small switch" size={SwitchSize.SMALL} /> // Medium size (default) <Switch checked={isEnabled} onChange={setIsEnabled} label="Medium switch" size={SwitchSize.MEDIUM} />
Switch States
Switches in various states
<Switch checked={true} onChange={() => {}} label="Normal state (checked)" /> <Switch checked={false} onChange={() => {}} label="Normal state (unchecked)" /> <Switch checked={true} onChange={() => {}} label="Required field" required={true} /> <Switch checked={false} onChange={() => {}} label="Disabled switch" disabled={true} /> <Switch checked={true} onChange={() => {}} label="Error state" error={true} />
Switch Group
Group of switches with multiple selections
import { Switch, SwitchGroup } from 'blend-v1' function MyComponent() { const [selectedFeatures, setSelectedFeatures] = useState<string[]>([ 'feature1', 'feature3', ]) return ( <SwitchGroup label="Feature toggles" value={selectedFeatures} onChange={setSelectedFeatures} > <Switch value="feature1" label="Real-time updates" subtext="Get instant notifications when data changes" /> <Switch value="feature2" label="Advanced analytics" subtext="Access detailed performance metrics" /> <Switch value="feature3" label="Dark mode" subtext="Switch to dark theme" /> <Switch value="feature4" label="Auto-sync" subtext="Automatically sync data across devices" /> </SwitchGroup> ) }
Controlled vs Uncontrolled
Switches with different state management approaches
// Controlled switch const [isEnabled, setIsEnabled] = useState(false); <Switch checked={isEnabled} onChange={setIsEnabled} label="Controlled switch" /> // Uncontrolled switch <Switch defaultChecked={true} label="Uncontrolled switch" />
Individual Switches
Switches used outside of a group
const [notifications, setNotifications] = useState(false); const [darkMode, setDarkMode] = useState(true); <Switch checked={notifications} onChange={setNotifications} label="Individual switch 1" subtext="This is an individual switch control" /> <Switch checked={darkMode} onChange={setDarkMode} label="Individual switch 2" slot={<span className="text-purple-500 text-sm">Beta</span>} />
Complex Form Example
Complete form with switch group
function EmailPreferencesForm() { const [emailSettings, setEmailSettings] = useState<string[]>([ 'marketing', 'updates', ]) return ( <div className="space-y-4"> <h3 className="text-lg font-semibold">Email Preferences</h3> <SwitchGroup label="Email notifications" value={emailSettings} onChange={setEmailSettings} > <Switch value="marketing" label="Marketing emails" subtext="Receive promotional offers and updates" slot={<span className="text-blue-500 text-sm">Weekly</span>} /> <Switch value="updates" label="Product updates" subtext="Get notified about new features and improvements" slot={ <span className="text-green-500 text-sm"> Important </span> } /> <Switch value="security" label="Security alerts" subtext="Critical security notifications" slot={ <span className="text-red-500 text-sm">Critical</span> } /> <Switch value="newsletter" label="Newsletter" subtext="Monthly newsletter with industry insights" /> </SwitchGroup> </div> ) }
Disabled Switch Group
Switch group with all options disabled
<SwitchGroup label="Disabled Options" value={selectedFeatures} onChange={setSelectedFeatures} disabled={true} > <Switch value="feature1" label="Feature 1" subtext="This feature is currently unavailable" /> <Switch value="feature2" label="Feature 2" subtext="Coming soon" /> <Switch value="feature3" label="Feature 3" subtext="Under maintenance" /> </SwitchGroup>
Switch with Different Content
Switches with various content types
<Switch checked={true} onChange={() => {}} label="Switch with icon" slot={<span>🔔</span>} /> <Switch checked={false} onChange={() => {}} label="Switch with badge" slot={<span className="bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded">New</span>} /> <Switch checked={true} onChange={() => {}} label="Switch with status" slot={<span className="text-green-500 text-sm">Active</span>} subtext="This feature is currently enabled" />
Component Tokens
You can style the switch component using the following tokens:
export type SwitchSize = 'sm' | 'md' export type SwitchState = 'default' | 'hover' | 'disabled' | 'error' export type SwitchIndicatorState = 'active' | 'inactive' export type SwitchTokensType = { // Base spacing gap: CSSObject['gap'] slotGap: CSSObject['gap'] contentGap: CSSObject['gap'] // Core dimensions height: { [key in SwitchSize]: CSSObject['height'] } width: { [key in SwitchSize]: CSSObject['width'] } // Border radius borderRadius: { base: CSSObject['borderRadius'] thumb: CSSObject['borderRadius'] } // Indicator (main switch) indicator: { [key in SwitchIndicatorState]: { background: { [key in Exclude< SwitchState, 'error' >]: CSSObject['backgroundColor'] } border: { [key in Exclude<SwitchState, 'error'>]: CSSObject['borderColor'] } } } // Thumb (moving circle) thumb: { background: CSSObject['backgroundColor'] border: { color: CSSObject['borderColor'] width: CSSObject['borderWidth'] } size: { [key in SwitchSize]: { width: CSSObject['width'] height: CSSObject['height'] top: CSSObject['top'] left: CSSObject['left'] offset: { active: CSSObject['left'] inactive: CSSObject['left'] } } } } // Content styling content: { label: { color: { [key in SwitchState]: CSSObject['color'] } font: { [key in SwitchSize]: { fontSize: CSSObject['fontSize'] fontWeight: CSSObject['fontWeight'] } } } sublabel: { color: { [key in SwitchState]: CSSObject['color'] } font: { [key in SwitchSize]: { fontSize: CSSObject['fontSize'] fontWeight: CSSObject['fontWeight'] } } spacing: { left: { [key in SwitchSize]: CSSObject['marginLeft'] } top: CSSObject['marginTop'] } } } // Border properties borderWidth: { [key in SwitchIndicatorState]: { [key in Exclude<SwitchState, 'error'>]: number } } // Focus state focus: { outline: { width: CSSObject['borderWidth'] color: CSSObject['borderColor'] offset: CSSObject['outlineOffset'] } } // Slot (additional content) slot: { size: { [key in SwitchSize]: CSSObject['width'] } spacing: CSSObject['margin'] } // Required indicator required: { color: CSSObject['color'] spacing: CSSObject['margin'] } // Animation transition: { duration: CSSObject['transitionDuration'] easing: CSSObject['transitionTimingFunction'] } }
Enums
SwitchSize
enum SwitchSize { SMALL = 'sm', MEDIUM = 'md', }
Type Definitions
SwitchState
type SwitchState = 'default' | 'hover' | 'disabled' | 'error'
SwitchIndicatorState
type SwitchIndicatorState = 'active' | 'inactive'
Accessibility Features
The Switch component includes several accessibility features:
- Proper ARIA attributes: Uses
role="switch"
andaria-checked
for screen readers - Keyboard navigation: Supports keyboard interaction (Space, Enter, Arrow keys)
- Screen reader support: Proper labeling and state announcements
- Focus management: Clear focus indicators and keyboard focus
- Required field indication: Visual and programmatic indication of required fields
- Error state communication: Clear error state communication to assistive technologies
- Group semantics: Proper switch group semantics for screen readers
- Smooth animations: Provides visual feedback for state changes
- High contrast support: Maintains accessibility in high contrast modes