Switch
An on/off control for a setting that takes effect immediately — no submit
required. Built on Base UI Switch, carrying the switch role and
aria-checked. For a value confirmed later on a form, use Checkbox.
Import
import { Switch } from "@photon-ai/pho-ui/components/switch";
Sizes
Two sizes — sm and md (default). A switch is intentionally compact; there
is no lg.
<Switch aria-label="Wi-Fi" size="sm" defaultChecked />
<Switch aria-label="Wi-Fi" defaultChecked />
States
Control with checked / onCheckedChange, or leave it uncontrolled with
defaultChecked. disabled dims and blocks interaction.
<Switch aria-label="Notifications" defaultChecked />
<Switch aria-label="Notifications" />
<Switch aria-label="Notifications" defaultChecked disabled />
With a label
A lone switch is ambiguous. Give it a visible <label> and tie the two
together with id / htmlFor — clicking the label then toggles the control.
This is also the shape of a controlled switch, driving checked from state via
onCheckedChange.
Join known networks automatically.
const [checked, setChecked] = useState(true);
<label htmlFor="wifi">Wi-Fi</label>
<Switch id="wifi" checked={checked} onCheckedChange={setChecked} />
Props
- size —
sm·md(defaultmd) - checked — controlled on/off state
- defaultChecked — uncontrolled initial state (default
false) - onCheckedChange —
(checked: boolean, event) => void, fired on toggle - disabled — non-interactive and dimmed (default
false) - readOnly — focusable but cannot be toggled (default
false) - required — must be on before the owning form submits (default
false) - name — field name for form submission
- value / uncheckedValue — value submitted when on / off (defaults to
the native checkbox behavior —
"on"when checked, nothing when unchecked) - form — id of the owning
<form>, for a switch rendered outside it - id — applied to the hidden
<input>, for pairing with a<label htmlFor> - inputRef — ref to the hidden
<input type="checkbox">element - className — extend or override the track styling
Accessibility
- Renders a
<span>withrole="switch"andaria-checkedreflecting the state, alongside a hidden native<input type="checkbox">that carries the value into form submission. - No implicit label — always pair the switch with a visible
<label htmlFor>(matched to the switch’sid) or anaria-label. A bare switch is unannounced. - Focus is shown with the brand focus ring (
focus-visibleonly), so pointer toggles stay quiet while keyboard users get a clear ring.
Keyboard:
- Tab — move focus to the switch
- Space / Enter — toggle it
disabled removes the switch from the tab order; readOnly keeps it focusable
but rejects the toggle.
Best practices
- Use a switch when the change applies the instant it’s flipped (dark mode,
notifications). If the user must press Save for it to count, use a
Checkbox. - Always give the switch a visible label or an
aria-label— a lone switch is ambiguous. - Don’t pair a switch with an explicit Apply button; that contradicts its immediate-effect meaning.