Skip to the content

Kongens Nytorv

Metro M1, M2 and M3.

Variants and states

RestHoverPressedFocusDisabled
Default
Default
  • Rest
  • Hover
  • Pressed
  • Focus
  • Disabled

Props

NameTypeDefaultDescription
checkedboolean—Whether the switch is on, when the caller controls it. Announced as on or off.
defaultCheckedbooleanfalseWhether the switch is on at first, when it keeps its state itself.
onChange(event: Event, value: boolean, details: Switch.Root.ChangeEventDetails) => void—Called when a click, Space or Enter, or a click on its label, turns the switch on or off, with the new state as value; details.reason is 'none', and details.cancel() keeps the state as it was. event is details.event, the hidden input's change.
disabledbooleanfalseWhether the switch ignores the pointer and the keys. It leaves the tab order, keeps its state, and is announced as dimmed.
readOnlybooleanfalseWhether the switch shows its state but can't be changed. It keeps its place in the tab order and is announced as read-only.
requiredbooleanfalseWhether the switch must be on before its form submits. Announced as required; the label says so to the eye.
namestring—The name the switch's value is submitted under in a native <form>. Inside a Base UI Field.Root, the field's name wins.
classNamestring—Reaches the root. className is merged after pn-Switch.
styleCSSProperties—Reaches the root. className is merged after pn-Switch.
refRef<HTMLElement>—Reaches the root. className is merged after pn-Switch.
slotProps{ thumb?: SwitchThumbProps | undefined; }—Props for each part: thumb.
checkedboolean, default —
Whether the switch is on, when the caller controls it. Announced as on or off.
defaultCheckedboolean, default false
Whether the switch is on at first, when it keeps its state itself.
onChange(event: Event, value: boolean, details: Switch.Root.ChangeEventDetails) => void, default —
Called when a click, Space or Enter, or a click on its label, turns the switch on or off, with the new state as value; details.reason is 'none', and details.cancel() keeps the state as it was. event is details.event, the hidden input's change.
disabledboolean, default false
Whether the switch ignores the pointer and the keys. It leaves the tab order, keeps its state, and is announced as dimmed.
readOnlyboolean, default false
Whether the switch shows its state but can't be changed. It keeps its place in the tab order and is announced as read-only.
requiredboolean, default false
Whether the switch must be on before its form submits. Announced as required; the label says so to the eye.
namestring, default —
The name the switch's value is submitted under in a native <form>. Inside a Base UI Field.Root, the field's name wins.
classNamestring, default —
Reaches the root. className is merged after pn-Switch.
styleCSSProperties, default —
Reaches the root. className is merged after pn-Switch.
refRef<HTMLElement>, default —
Reaches the root. className is merged after pn-Switch.
slotProps{ thumb?: SwitchThumbProps | undefined; }, default —
Props for each part: thumb.

Use it

import { Switch } from '@mylder/perron'

Ask your agent

get_reference({ library: "base-ui", component: "Switch" })

Keyboard and ARIA

From the Base UI reference for Switch and the installed SwitchRoot and useButton. "From" says who does it.

KeyDoesFrom
Tab, Shift+TabMoves focus to the switch and away; a disabled switch is skipped, a read-only one is notThe browser, and Base UI's tabIndex
SpaceTurns the switch on or off on release, through the hidden input's click, and calls onChange with the new state; nothing while read-only or disabledBase UI
EnterTurns the switch on or off on press, the same way; nothing while read-only or disabledBase UI

Switch adds no keys of its own.

ElementRoleAccessible name fromStates announced
rootswitch, from Base UI, on a <span>The caller's aria-label, aria-labelledby, a wrapping <label>, a <label> whose htmlFor is its id, or a Field.Label, which Base UI turns into aria-labelledbyaria-checked, on or off; aria-disabled; aria-readonly; aria-required; aria-invalid in an invalid Field
thumbnone: a <span> with no contentnonenone
inputnone: aria-hidden="true", tabIndex −1nonenone

What axe won't catch, from the contract, each with how this component meets it:

  • Everything the eye is told, the ear is told, for every shape each prop accepts: the thumb's place and the track's fill are aria-checked, heard as on or off after the name; a disabled switch's tertiary colours are aria-disabled, heard as dimmed; a read-only switch is aria-readonly; an invalid one's danger edge is aria-invalid, with the Field's message as its description.
  • Every landmark and named region has an accessible name: none here; a switch is neither. Its own name comes from the caller, which every story gives (CR-3).
  • Every default label can be overridden: none here; the switch owns no strings.
  • Every shape the type accepts renders, in every variant: the switch takes no ReactNode prop; every combination of checked, disabled and readOnly renders, as the stories show.
  • A hidden copy kept for animation is aria-hidden, and a collapsed region is inert: the hidden input is Base UI's, aria-hidden and out of the tab order; nothing collapses.
  • Native semantics first: Base UI's role="switch" on a <span>, with a native <input type="checkbox"> beside it for the label and the form; with render and nativeButton, a native <button>.
  • Focus moves in reading order and returns on close: the switch is one tab stop in document order, focus stays on it when it toggles, and a click on its label moves focus to it; it opens nothing to return from.
  • Every target is at least size.target-min square: the smallest target is the track itself, 40 × 24 px, and a wrapping <label> makes its text a target too.
  • Loops stop when the system asks for less motion: no loop; the thumb's slide and the fill's change are transitions over duration.switch, which the tokens shorten to 0.01 ms under reduced motion (CR-6).

Owned strings

The switch shows no "On" or "Off" word, though Accessibility asks toggles to say their state in words as well as in looks. That rule asks for the state once, either in words that change on a plain button, such as "Follow" and "Following", or from the role of a control whose label stays the same; a switch's label names the setting and stays the same, Base UI's role="switch" says on or off to the ear in every locale with no word of Perron's, and the eye gets the thumb's place as well as the fill, so the state never rests on colour alone. A word beside every switch would also lengthen each settings row in Danish, and the caller can still write one in the label.

No owned strings: every word comes from the caller, as the label or aria-label.

Do and don't

For a caller using the component, with the reason. Each row is a rule: a must row's Don't is never right, a should row's needs a reason, and Checked by says what catches the Don't in a caller's code.

RuleLevelDoDon'tChecked by
DD-1mustUse a Switch for a setting that takes effect the moment it changes, such as showing vehicle trails or the stations on the mapUse it for an answer a form sends later with a button: a checkbox says "choose now, apply on submit", where a switch says "this is on now"review
DD-2mustName it with a visible <label> or a Field's label that names the setting, in sentence case: "Show vehicle trails"Leave it unnamed, or name it with aria-label where there is room for a visible label: a sighted person can't tell what an unlabelled switch turns onreview
DD-3mustKeep the label the same whether the switch is on or offWrite the state in the label, "Trails on", or swap it when the switch flips: the switch already says on or off, and a changing label reads as a second statereview
DD-4shouldPut the label before the switch in a settings row, and let a long label wrapSqueeze the switch to fit a long label, or cut the label off: the track keeps its size, and a Danish label is longer than its Englishreview
DD-5shouldFilter the map's vehicles with a FilterChip, and pick one way of showing a view with a SegmentedControlUse a row of switches for one choice of several, or for the top bar's filters: switches each turn their own setting on, and a chip shows its countreview
DD-6mustRun an action, such as following a vehicle, with a ButtonUse a switch to start something that then runs on its own: a switch holds a state, it doesn't trigger onereview
DD-7shouldSay why a switch is disabled or read-only, in its label or the Field's descriptionDisable a switch with no word of why: a dimmed switch can't explain itselfreview