V2 componentsUpdated Oct 14, 2026
Toggle
A switch for a setting that applies the moment it flips, with no Save under it. Use Checkbox instead when the choice is collected and submitted later, or when picking several items from a list. Built on Base UI Switch, so it is role="switch" with Space, form participation and Field wiring included.
Source: packages/ui/src/components/toggle
import { Toggle } from '@highlight/ui'Change the props; the preview and the snippet update together.
<Field orientation="justified"> <Field.Label nativeLabel={false}> Lock telemetry off </Field.Label> <Toggle checked onCheckedChange={setChecked} /></Field>The usual home: a justified Field, label filling the row, toggle at the far end, note under the label. Pass nativeLabel={false} so hovering the words does not light the track.
import { useState } from 'react'import { Field, Toggle } from '@highlight/ui' export default function ToggleSettingsRow() { const [domainJoin, setDomainJoin] = useState(true) return ( <Field.Group orientation="justified" className="max-w-md"> <Field> <Field.Label nativeLabel={false}>Anyone with an @acme.com email can join</Field.Label> <Field.Note> {domainJoin ? 'Verified domain. Turn off to allow only people you invite.' : 'Verified domain. Only people you invite can join.'} </Field.Note> <Toggle checked={domainJoin} onCheckedChange={setDomainJoin} /> </Field> <Field> <Field.Label nativeLabel={false}>Lock telemetry off</Field.Label> <Field.Note>Stops members sharing data to evaluate AI quality.</Field.Note> <Toggle /> </Field> <Field disabled> <Field.Label nativeLabel={false}>Single sign-on</Field.Label> <Field.Note>Managed by your identity provider.</Field.Note> <Toggle defaultChecked /> </Field> </Field.Group> )}Off, on, and disabled in both positions. Disabled works like a disabled Button: the fill drops to the disabled wash in both positions, the thumb’s side still says which way it is set, and hover and press do nothing; never make a disabled toggle the only place a fact appears. Without a visible label, pass aria-label.
import { Toggle } from '@highlight/ui' export default function ToggleBasic() { return ( <div className="flex items-center gap-4"> <Toggle aria-label="Auto-join meetings" defaultChecked /> <Toggle aria-label="Share transcripts" /> <Toggle aria-label="Managed setting, on" disabled defaultChecked /> <Toggle aria-label="Managed setting, off" disabled /> </div> )}md (20px) for a settings list, sm (16px) for a dense row or a toolbar. There is no larger size.
import { Toggle } from '@highlight/ui' export default function ToggleSizes() { return ( <div className="flex items-center gap-4"> <Toggle size="sm" aria-label="Small" defaultChecked /> <Toggle size="md" aria-label="Medium" defaultChecked /> </div> )}The root, then any compound sub-components. Every part accepts className and forwards the rest of its props to the element or Base UI part beneath it.
Toggle- Base UI Switch.Root. The track and its thumb in one; checked, disabled, size and onCheckedChange live here.
Props added on top of the underlying element or Base UI part.
| Prop | Type | Default | Description |
|---|---|---|---|
size | 'sm' | 'md' | 'md' | Track height; every other dimension is a ratio of it. |
checked / defaultChecked | boolean | — | Controlled or uncontrolled state. |
onCheckedChange | (checked: boolean) => void | — | Fires on click, Space, or a label click. |
- All Base UI Switch.Root props pass through: name, value, required, readOnly, disabled.
- The thumb stretches as it crosses the track and settles at the end. It runs off one registered custom property, --toggle-throw (base.css), and is off under prefers-reduced-motion.
- Pressing and holding stretches the thumb about 20% toward where it will travel (--toggle-press).