Switch
Toggle switch for on/off settings that take effect immediately, without a Save step.
role="switch" button with aria-checked; aria-busy set during loading state.
Preview
tsx
import { Switch } from '@arshad-shah/cynosure-react';
import { useState } from 'react';
export default function Example() {
const [enabled, setEnabled] = useState(false);
return (
<Switch checked={enabled} onCheckedChange={setEnabled}>
{enabled ? 'Enabled' : 'Disabled'}
</Switch>
);
}
The thumb is small at rest and grows to fill the track as it slides on (a Material-You-style grow + slide). Use checkedIcon / uncheckedIcon to place a glyph in the thumb — e.g. a sun/moon for a theme toggle.
Three sizes are available: sm, md (default), and lg.
Preview
tsx
import { Switch } from '@arshad-shah/cynosure-react';
export default function Example() {
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem' }}>
<Switch size="sm" defaultChecked>
Small
</Switch>
<Switch size="md" defaultChecked>
Medium (default)
</Switch>
<Switch size="lg" defaultChecked>
Large
</Switch>
</div>
);
}
Disabled state
Section titled “Disabled state” Preview
tsx
import { Switch } from '@arshad-shah/cynosure-react';
export default function Example() {
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem' }}>
<Switch disabled>Disabled (off)</Switch>
<Switch disabled defaultChecked>
Disabled (on)
</Switch>
</div>
);
}
PropTypeDefaultDescription
checked
boolean
—
Controlled checked state.
defaultChecked
boolean
—
Uncontrolled initial checked state.
onCheckedChange
((checked: boolean) => void|Promise<unknown>)
—
Fires with the next checked state on toggle. May return a `Promise`: the
switch then flips optimistically to the new state, shows a spinner while
the promise is pending, **commits** on resolve, and **reverts** on reject.
value
string
—
Submitted value when checked.
loading
boolean
false
Forces the loading spinner and blocks interaction. Use for externally
managed async work; when `onCheckedChange` returns a promise the spinner
is shown automatically and you don't need this.
checkedIcon
ReactNode
—
Icon shown inside the thumb when **on**. Defaults to a checkmark (hidden
at `sm`). Pass `null` to suppress it, or any node to customize (e.g. a
sun/moon for a theme toggle).
uncheckedIcon
ReactNode
—
Icon shown inside the thumb when **off**. When set, the resting thumb
stays full-size (instead of the Material-style shrink) so the icon fits.
children
ReactNode
—
Optional label rendered alongside the control.
className
string
—
disabled
boolean
—
Disables interaction and dims the control.
required
boolean
—
Marks the control as required for form submission.
invalid
boolean
—
Renders the invalid state and sets `aria-invalid`.
name
string
—
Submitted form field name.
id
string
—
Element id — auto-generated when omitted.
autoFocus
boolean
—
Focuses the control on mount.
size
"sm"|"md"|"lg"
"md"
Control size.
Accessibility
Section titled “Accessibility”- Renders a
role="switch"button witharia-checkedreflecting on/off state. loadingsetsaria-busy="true"and blocks all interaction while async work completes.- Space key toggles the switch; focus ring follows design tokens.
Recipes
Section titled “Recipes”- Prefer
<Switch>over<Checkbox>when the action takes effect immediately (e.g. enabling a feature flag). - For async toggles, return a promise from
onCheckedChange: the switch flips optimistically to the new state, shows a spinner while pending, keeps the change on success, and reverts on rejection. (Theloadingprop is still available for externally managed spinners.) The thumb stays full-size while the spinner shows — even when toggling off — then shrinks back once it settles. - Pass
checkedIcon/uncheckedIconto put a glyph in the thumb — e.g. a sun/moon for a theme toggle.