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 NameType
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 NameType
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" and aria-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