Switch
A binary on/off control, built on a real <input type="checkbox" role="switch"> — which is exactly what WAI-ARIA describes a switch as.
Usage#
import { Switch } from "neelam-ui";
<label className="flex items-center gap-3">
<Switch defaultChecked />
Enable notifications
</label>Switch or checkbox?#
They are the same element underneath, and the choice is about meaning rather than mechanics:
- Switch — the change takes effect immediately. Turning it on is the action. Think a settings pane with no Save button.
- Checkbox — the value is collected now and submitted later, as part of a form. Think terms-and-conditions, or a filter you apply afterwards.
A switch needs no Save button
If the surrounding form has one, the control almost certainly wants to be a
Checkbox instead.
Switch is Checkbox's sibling in every respect but the visual and the
tri-state: there is no indeterminate here, because a switch is always simply
on or off.
Controlled#
const [enabled, setEnabled] = useState(false);
<Switch checked={enabled} onCheckedChange={setEnabled} />Keyboard#
| Key | Behaviour |
|---|---|
| Tab | Moves focus to the switch. Disabled switches are skipped. |
| Space | Toggles the switch — native checkbox behaviour. |
Accessibility#
- A native
<input type="checkbox">carryingrole="switch", so keyboard toggling, form participation, and checked-state exposure all come from the platform. A hand-rolled<button role="switch">would have to re-implement each of those. - Screen readers announce "on"/"off" rather than "checked"/"unchecked", which is
what the
switchrole buys over a plain checkbox. - The sliding thumb is
aria-hidden— the input's owncheckedproperty already carries the state. - The thumb's transition is dropped under
prefers-reduced-motion.
Label the switch, not just the row
<label> wrapping the switch and its text is the reliable association. A
heading sitting above a column of switches names the group, not any one
control.
API reference#
| Prop | Type | Default |
|---|---|---|
checked | boolean | — |
defaultChecked | boolean | — |
onCheckedChange | ((checked: boolean) => void) | — |
Also accepts every native <input> attribute except type — name,
disabled, required, aria-*, and the rest.