A pressable button that toggles between pressed and unpressed states. Built on role="button" with aria-pressed, it emits change events and supports both button and non-button root elements.
When the root is a native <button>, the controller sets type="button" (if not already set) to prevent accidental form submission. Button elements handle click and keyboard events natively.
Data Slots
Slot
Required
Description
toggle
Yes
Root element. Receives aria-pressed and state.
Generated Attributes
Attribute
Element
Description
data-state
Root
"on" when pressed, "off" when not pressed.
aria-pressed
Root
"true" or "false".
aria-disabled
Root
"true" when disabled (on all element types).
disabled
Root
Native attribute set on <button> elements when disabled.
type
Root
Set to "button" on <button> elements to prevent form submission (unless already set).
role
Root
Set to "button" when the root is not already a <button>.
Dispatch on the root to programmatically set the pressed state. Blocked when disabled.
API Reference
Options
Option
Type
Default
Description
defaultPressed
boolean
false
Initial pressed state.
disabled
boolean
false
Disable user interaction.
onPressedChange
(pressed: boolean) => void
—
Called when the pressed state changes.
Controller
Member
Type
Description
pressed
boolean (getter)
Current pressed state.
toggle()
() => void
Toggle the pressed state. Always works, even when disabled.
press()
() => void
Set pressed to true. Always works, even when disabled.
release()
() => void
Set pressed to false. Always works, even when disabled.
destroy()
() => void
Remove all listeners and clean up.
Controller
The controller is returned by Toggle.createToggle() and provides imperative control over the pressed state.
const controller = Toggle.createToggle(root);// Togglecontroller.toggle();// Set pressed to truecontroller.press();// Set pressed to falsecontroller.release();// Read current stateconsole.log(controller.pressed); // true | false// Clean upcontroller.destroy();
Disabled vs. Programmatic Control
User interaction (clicks) and inbound events (toggle:set) are blocked when the toggle is disabled. However, the controller methods (toggle(), press(), release()) always work regardless of disabled state. This allows you to have explicit programmatic control while still blocking user input.
Button vs. Non-Button Elements
Button elements: The controller sets type="button" to prevent form submission (unless a type is already specified). Button elements handle keyboard interaction (Enter/Space) natively, so no additional keyboard handlers are added.
Non-button elements: The controller sets role="button" and tabindex="0". The element’s native click event (from mouse or keyboard) toggles the state.