Toggle is an on/off switch. The switch you see is one element; the control a screen reader meets is a hidden
checkbox with role="switch" beside it. It is fully controlled, so the thumb
moves when you update value and not when the reader presses it.
ToggleField is the one to render inside a form layout, though it buys less
than the other composed fields do.
Anatomy
Section titled “Anatomy”-
Label (optional) what the switch controls. Set labelOn and labelOff where the wording should change with the state. -
Switch the control. Track and thumb are one element: PDS paints both as pseudo-elements on it, so the thumb has no box of its own and its position is the state.
The label sits to the left of the switch, which is the opposite side from
Checkbox and Radio. labelOn and labelOff take a label each, for the cases where the
wording has to change with the state, and labelOff falls back to labelOn, so
a single label is the ordinary case, and it is part of the target: clicking the
label throws the switch. The thumb slides between the two ends, and that slide
is the only motion in the control.
When to use
Section titled “When to use”A toggle takes effect as it is switched, and there is nothing between the press and the consequence: no submit step, no confirmation, no undo. The setting behind one has to be safe to throw and safe to throw back.
The switch keeps its own label even inside a field
Section titled “The switch keeps its own label even inside a field”ToggleField is a toggle in a FormField, which gets
the switch a label above it, helper text, warning text and error text in the
same fixed order every other field uses, and rightActions beside the label.
Render it wherever a toggle sits in a form among other fields, so the switch
lines up with them.
What it does not do is connect the two. Toggle generates its own input id and
ignores the one the field passes down, so the field’s label is a heading over
the switch rather than its accessible name — the switch is still named by
labelOn, labelOff or aria-label. The same is true of
Slider, List Box and
Swatch Picker, and it is why the two label props are
worth keeping even when the field draws a label.
disabled is the one thing that does travel: a ToggleField marked disabled
disables the switch through context. Because ToggleField forwards every other
field prop untouched, there is no toggle-specific reason to compose a
FormField by hand — only the general one, which is a
field slot holding more than the switch.
A toggle inside a form posts nothing
Section titled “A toggle inside a form posts nothing”Toggle submits nothing, because its hidden input carries no name and no value. A
toggle inside a <form> contributes nothing to what the form posts, and its
state exists only in the variable you passed to value. Where the answer should
travel with the form, the control is a Checkbox. Where
the reader is choosing between two named alternatives rather than turning one
thing on, it is Radio.
Confirm a change with a button, not a switch
Section titled “Confirm a change with a button, not a switch”There is no pending state and no confirm step: onChange fires on the press,
and the next thing the reader sees is the consequence. A change worth confirming
needs a button and a Modal instead. A toggle also stays
where it is put, so a mode that ought to expire on its own is not one.
States
Section titled “States”The parent owns the value, and anything falsy is off
Section titled “The parent owns the value, and anything falsy is off”The parent owns the state. onChange hands you the next boolean and that is all
Toggle does with it: the hidden input is read-only and the switch renders from
value, so a parent that does not store the new value leaves the reader
pressing a switch that will not move. There is no uncontrolled mode.
value is required and deliberately loose: false, null, undefined and the
empty string all count as off. A value that has not loaded yet therefore renders
as a switch in the off position rather than as nothing, which is worth knowing
before you show a toggle for a setting you are still fetching.
Take over the tooltip on the switch
Section titled “Take over the tooltip on the switch”Every toggle carries a title on its root element, defaulting to “On” and
“Off”, so hovering one for a moment produces a browser tooltip naming the state.
titleOn and titleOff replace those strings, and passing an empty string
removes the tooltip. Replace them or remove them: a tooltip reading “On” repeats
what the thumb’s position already said, and spends the one gesture that could
have explained the setting.
Accessibility
Section titled “Accessibility”An unnamed switch names its own mechanism
Section titled “An unnamed switch names its own mechanism”With labelOn or labelOff, the rendered label carries a for attribute
pointing at the hidden input, and that is what names it. With no label and no
aria-label, Toggle falls back to aria-label="Toggle on" or "Toggle off",
which is the control’s own mechanism and its current state and not one word
about what is being switched. Set aria-label on any toggle without a visible
label — including one whose only label comes from a ToggleField — and name
what it controls.
Check where a disabled toggle was disabled
Section titled “Check where a disabled toggle was disabled”disabled disables the hidden input, which takes the toggle out of the tab
order altogether: a keyboard reader never reaches it, and the muted styling is
the whole of the notice they get. It can also arrive from an enclosing
Form Field instead of from the prop, so a toggle can be
unreachable without anything in its own props saying so. Where that is
deliberate, the reason belongs in the text beside it.
Content
Section titled “Content”Name what is switched, and keep the label true in both positions
Section titled “Name what is switched, and keep the label true in both positions”“Email notifications” reads correctly whichever way the switch is thrown. “Don’t send email” does not: switched on it means email is off, and the reader has to hold two negations at once to work out what they have just done. Let the thumb’s position carry on and off, and let the label carry the subject.
Where the wording genuinely has to change, give labelOn and labelOff
wordings that both still name the setting. Sentence case and punctuation are on
Writing.
ToggleField is every prop below plus the twelve FormField carries:
| Name | Type |
|---|---|
label |
Renders |
inputId |
ID of the input element. Providing this will automatically link the label to the input. |
helperText |
Renders |
errorText |
Renders |
warningText |
Renders |
labelProps |
|
helperProps |
|
warningProps |
|
errorProps |
|
configField |
Whether to render the form field as a config field. This will render the helper text as a tooltip. |
configFieldInputWidth |
Override the width of the input area when |
rightActions |
Renders actions to the right of the label. |
className |
|
disabled |
Disables interaction and renders the toggle in a muted style. |
titleOff |
Tooltip / title shown on the root element when the toggle is off. |
titleOn |
Tooltip / title shown on the root element when the toggle is on. |
onChange |
Called with the new boolean value when the user clicks the toggle. The component is fully controlled — you must update |
valuerequired |
Current on/off state. Falsy values ( |
id |
|
labelOn |
Label node rendered to the left of the switch when the toggle is on. |
labelOff |
Label node rendered to the left of the switch when the toggle is off. Falls back to |
data-test |
|
aria-label |
Accessible label for the hidden |
size |
Size of the toggle switch. |
Toggle’s own props, which ToggleField also accepts:
| Name | Type |
|---|---|
className |
|
disabled |
Disables interaction and renders the toggle in a muted style. |
titleOff |
Tooltip / title shown on the root element when the toggle is off. |
titleOn |
Tooltip / title shown on the root element when the toggle is on. |
onChange |
Called with the new boolean value when the user clicks the toggle. The component is fully controlled — you must update |
valuerequired |
Current on/off state. Falsy values ( |
id |
|
labelOn |
Label node rendered to the left of the switch when the toggle is on. |
labelOff |
Label node rendered to the left of the switch when the toggle is off. Falls back to |
data-test |
|
aria-label |
Accessible label for the hidden |
size |
Size of the toggle switch. |
Was this page helpful?