Skip to main content
The Switch component provides a toggle control for turning options on or off, similar to a physical light switch.

Basic usage

import { Switch } from '@raystack/apsara';

function App() {
  return <Switch />;
}

Props

checked
boolean
The controlled checked state of the switch.
defaultChecked
boolean
The default checked state for uncontrolled usage.
onCheckedChange
(checked: boolean) => void
Callback fired when the checked state changes.
disabled
boolean
Whether the switch is disabled.
required
boolean
Whether the switch is required.
name
string
The name of the switch input for form submission.
value
string
The value of the switch input when checked.
size
'small' | 'large'
default:"'large'"
The size of the switch.
className
string
Additional CSS classes to apply to the switch.

Controlled switch

function ControlledSwitch() {
  const [enabled, setEnabled] = useState(false);

  return (
    <label>
      <Switch checked={enabled} onCheckedChange={setEnabled} />
      <span>Enable notifications</span>
    </label>
  );
}

Uncontrolled switch

<Switch defaultChecked />

Size variants

<Switch size="small" />
<Switch size="large" />

Disabled state

<Switch disabled />
<Switch disabled checked />

With labels

<div>
  <label>
    <span>Dark mode</span>
    <Switch />
  </label>
  
  <label>
    <span>Auto-save</span>
    <Switch defaultChecked />
  </label>
  
  <label>
    <span>Email notifications</span>
    <Switch />
  </label>
</div>

With descriptions

<div>
  <div>
    <label>
      <div>
        <strong>Marketing emails</strong>
        <p>Receive emails about new products and features</p>
      </div>
      <Switch />
    </label>
  </div>
  
  <div>
    <label>
      <div>
        <strong>Security alerts</strong>
        <p>Get notified about important security updates</p>
      </div>
      <Switch defaultChecked />
    </label>
  </div>
</div>

With form integration

<form>
  <label>
    <Switch name="notifications" value="enabled" />
    <span>Enable notifications</span>
  </label>
  <button type="submit">Save settings</button>
</form>

Required switch

<label>
  <Switch required />
  <span>I agree to the terms and conditions *</span>
</label>

Settings panel example

function SettingsPanel() {
  const [settings, setSettings] = useState({
    darkMode: false,
    notifications: true,
    autoSave: true,
    analytics: false
  });

  const updateSetting = (key, value) => {
    setSettings(prev => ({ ...prev, [key]: value }));
  };

  return (
    <div>
      <h3>Settings</h3>
      
      <label>
        <span>Dark mode</span>
        <Switch
          checked={settings.darkMode}
          onCheckedChange={(checked) => updateSetting('darkMode', checked)}
        />
      </label>
      
      <label>
        <span>Notifications</span>
        <Switch
          size="small"
          checked={settings.notifications}
          onCheckedChange={(checked) => updateSetting('notifications', checked)}
        />
      </label>
      
      <label>
        <span>Auto-save</span>
        <Switch
          checked={settings.autoSave}
          onCheckedChange={(checked) => updateSetting('autoSave', checked)}
        />
      </label>
      
      <label>
        <span>Analytics</span>
        <Switch
          checked={settings.analytics}
          onCheckedChange={(checked) => updateSetting('analytics', checked)}
        />
      </label>
    </div>
  );
}

Accessibility

  • Built on Base UI Switch primitive with full accessibility support.
  • Proper ARIA attributes including role=“switch” are automatically applied.
  • Supports keyboard navigation with Space to toggle.
  • Checked state is properly communicated to screen readers.
  • Works seamlessly within forms with proper name/value attributes.
  • Label association ensures the entire label area is clickable.