Skip to main content
A toggle switch for binary on/off states.

Import

import { Switch } from '@base-ui/react/switch';

Anatomy

The Switch component consists of two parts:
  • Switch.Root - The switch control itself
  • Switch.Thumb - The draggable thumb element

Basic Usage

<Switch.Root>
  <Switch.Thumb />
</Switch.Root>

Key Features

  • Controlled and uncontrolled modes
  • Accessible with proper ARIA attributes
  • Works seamlessly with Field and Form components
  • Custom render props
  • Support for read-only and disabled states

Key Props

checked

Type: boolean Whether the switch is currently active. Use with onCheckedChange for controlled mode.
const [checked, setChecked] = React.useState(false);

<Switch.Root checked={checked} onCheckedChange={setChecked}>
  <Switch.Thumb />
</Switch.Root>

defaultChecked

Type: boolean Default: false Whether the switch is initially active. Use for uncontrolled mode.
<Switch.Root defaultChecked>
  <Switch.Thumb />
</Switch.Root>

onCheckedChange

Type: (checked: boolean, eventDetails: ChangeEventDetails) => void Event handler called when the switch is activated or deactivated.
<Switch.Root onCheckedChange={(checked) => console.log('Switch:', checked)}>
  <Switch.Thumb />
</Switch.Root>

disabled

Type: boolean Default: false Whether the component should ignore user interaction.
<Switch.Root disabled>
  <Switch.Thumb />
</Switch.Root>

readOnly

Type: boolean Default: false Whether the user should be unable to activate or deactivate the switch.

required

Type: boolean Default: false Whether the user must activate the switch before submitting a form.

name

Type: string Identifies the field when a form is submitted.

value

Type: string The value submitted with the form when the switch is on.

uncheckedValue

Type: string The value submitted with the form when the switch is off.

inputRef

Type: React.Ref<HTMLInputElement> A ref to access the hidden input element.

Styling

<Switch.Root className="relative w-11 h-6 rounded-full bg-gray-200 data-[checked]:bg-blue-500 transition-colors">
  <Switch.Thumb className="absolute left-0.5 top-0.5 w-5 h-5 rounded-full bg-white shadow-md transition-transform data-[checked]:translate-x-5" />
</Switch.Root>

Common Patterns

With Label

import { Field } from '@base-ui/react/switch';

<Field.Root>
  <div className="flex items-center justify-between">
    <Field.Label>Enable notifications</Field.Label>
    <Switch.Root name="notifications">
      <Switch.Thumb />
    </Switch.Root>
  </div>
</Field.Root>

Settings List

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

  return (
    <div className="space-y-4">
      <div className="flex items-center justify-between">
        <div>
          <div className="font-medium">Push Notifications</div>
          <div className="text-sm text-gray-500">Receive push notifications</div>
        </div>
        <Switch.Root
          checked={settings.notifications}
          onCheckedChange={(checked) =>
            setSettings({ ...settings, notifications: checked })
          }
        >
          <Switch.Thumb />
        </Switch.Root>
      </div>
      
      <div className="flex items-center justify-between">
        <div>
          <div className="font-medium">Dark Mode</div>
          <div className="text-sm text-gray-500">Use dark theme</div>
        </div>
        <Switch.Root
          checked={settings.darkMode}
          onCheckedChange={(checked) =>
            setSettings({ ...settings, darkMode: checked })
          }
        >
          <Switch.Thumb />
        </Switch.Root>
      </div>
    </div>
  );
}

With Icons

<Switch.Root className="relative w-14 h-7 rounded-full bg-gray-200 data-[checked]:bg-blue-500">
  <Switch.Thumb className="absolute left-1 top-1 w-5 h-5 rounded-full bg-white flex items-center justify-center transition-transform data-[checked]:translate-x-7">
    <svg className="w-3 h-3" fill="currentColor">
      <path d="M12 2.25a.75.75 0 01.75.75v2.25a.75.75 0 01-1.5 0V3a.75.75 0 01.75-.75zM7.5 12a4.5 4.5 0 119 0 4.5 4.5 0 01-9 0z" />
    </svg>
  </Switch.Thumb>
</Switch.Root>

Form Integration

import { Form, Field } from '@base-ui/react/switch';

<Form.Root>
  <Field.Root name="terms" required>
    <div className="flex items-center gap-3">
      <Switch.Root>
        <Switch.Thumb />
      </Switch.Root>
      <Field.Label>
        I agree to the terms and conditions
      </Field.Label>
    </div>
    <Field.Error />
  </Field.Root>
</Form.Root>

Color Variants

function ColoredSwitch() {
  const [checked, setChecked] = React.useState(false);

  return (
    <Switch.Root
      checked={checked}
      onCheckedChange={setChecked}
      className="relative w-11 h-6 rounded-full bg-gray-200 data-[checked]:bg-green-500"
    >
      <Switch.Thumb className="absolute left-0.5 top-0.5 w-5 h-5 rounded-full bg-white shadow transition-transform data-[checked]:translate-x-5" />
    </Switch.Root>
  );
}