Morphos
Inputs

Toggle

A stateful button that can be pressed or unpressed, with aria-pressed semantics.

Interactive example

Open in Storybook

Installation

npm install @morphos/inputs
pnpm add @morphos/inputs
yarn add @morphos/inputs
bun add @morphos/inputs

Import

import { Toggle } from '@morphos/inputs'

Usage

@Component()
class MyComponent extends StatefulComponent {
  @State() bold = false

  render() {
    return (
      <Toggle
        pressed={this.bold}
        onPressedChange={(pressed) => (this.bold = pressed)}
        aria-label="Bold"
      >
        <strong>B</strong>
      </Toggle>
    )
  }
}

Uncontrolled

@Component()
class MyComponent extends StatefulComponent {
  render() {
    return (
      <Toggle defaultPressed={false} aria-label="Mute audio">
        <span>Mute</span>
      </Toggle>
    )
  }
}

Toolbar example

@Component()
class MyComponent extends StatefulComponent {
  @State() bold = false
  @State() italic = false
  @State() underline = false

  render() {
    return (
      <div role="toolbar" aria-label="Text formatting">
        <Toggle
          pressed={this.bold}
          onPressedChange={(v) => (this.bold = v)}
          aria-label="Bold"
        >
          B
        </Toggle>
        <Toggle
          pressed={this.italic}
          onPressedChange={(v) => (this.italic = v)}
          aria-label="Italic"
        >
          I
        </Toggle>
        <Toggle
          pressed={this.underline}
          onPressedChange={(v) => (this.underline = v)}
          aria-label="Underline"
        >
          U
        </Toggle>
      </div>
    )
  }
}

Props — Toggle

PropTypeDefaultDescription
pressedboolean—Controlled pressed state
defaultPressedbooleanfalseUncontrolled initial pressed state
disabledbooleanfalseDisables the toggle
onPressedChange(pressed: boolean) => void—Fires when the pressed state changes
classstring—Additional CSS classes
idstring—HTML id attribute
childrenChildren—Content rendered inside the button
aria-labelstring—Accessible label (required when children are not descriptive)
aria-labelledbystring—ID of an element that labels the toggle
aria-describedbystring—ID of an element that describes the toggle

data-* attributes

AttributeElementWhen present
data-pressedRootThe toggle is currently pressed
data-disabledRootdisabled is true

Keyboard navigation

KeyBehavior
SpaceToggle the pressed state
EnterToggle the pressed state
TabMove focus to the next focusable element

Accessibility

Toggle renders as a <button> with aria-pressed set to "true" or "false" depending on state. When disabled is true, the button receives the native disabled HTML attribute (button elements are automatically excluded from focus and click when disabled). Always provide a descriptive aria-label when the button content is a visual icon.

For groups of mutually exclusive or multi-selectable toggles, use ToggleGroup and ToggleGroupItem instead — they share selection state through a single group instance.

Styling example

.morphos-toggle[data-pressed] {
  background: var(--morphos-color-accent);
  border-color: var(--morphos-color-accent);
  color: var(--morphos-color-accent-text);
}

.morphos-toggle[data-disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}

On this page