Skip to content

Toggle

<button class="toggle" type="button" aria-pressed="false" aria-label="Bold"></button>

aria-pressed is both the state and the styling hook, so flipping the attribute is the whole update — there is no second class to keep in sync. A <button> that carries the attribute is flipped for you on click, because nothing in the platform does it: a pressed button holds its own state, unlike a checkbox.

AttributeMeaning
aria-pressedThe state, and what the styling reads
data-pk-controlledLeave the state alone — you set aria-pressed yourself
data-valueCarried in the change event

Each press fires pk:toggle:change on the button:

document.addEventListener("pk:toggle:change", (event) => {
console.log(event.detail.pressed, event.detail.value);
});

A toolbar toggle is a button, but a toggle that submits a value is a checkbox. Wrap one in the label and the styling follows :checked instead of aria-pressed.

<label class="toggle toggle-outline">
<input class="sr-only" type="checkbox" name="notify" value="email" />
Email
</label>

A toggle is a button that stays pressed — bold, italic, a filter that is on. A switch is a setting. If it reads as “on/off” rather than “pressed/not pressed”, it is a switch.

Set dir="rtl" on the page or on any subtree — icon padding follows the reading direction. See the button page for a live example.

  • An icon-only toggle needs a name: aria-label, or .sr-only text inside it.
  • The name says what it controls, not its state. “Bold”, not “Bold is on” — aria-pressed already announces the state.
  • Do not swap the icon to convey state. A play icon becoming a pause icon is ambiguous; keep the icon and let aria-pressed carry the change.
  • The checkbox form keeps the input focusable. .sr-only hides it visually without taking it out of the tab order, which display: none would.