Morphos
Inputs

Switch

A toggle switch component with ARIA switch semantics and optional form participation.

Interactive example

Installation

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

Import

import { Switch } from '@morphos/inputs'

Usage

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

  render() {
    return (
      <label>
        <Switch
          checked={this.darkMode}
          onCheckedChange={(checked) => (this.darkMode = checked)}
        />
        Dark mode
      </label>
    )
  }
}

Uncontrolled

@Component()
class MyComponent extends StatefulComponent {
  render() {
    return (
      <label>
        <Switch defaultChecked={true} name="notifications" value="enabled" />
        Enable notifications
      </label>
    )
  }
}

Inside a form

@Component()
class MyComponent extends StatefulComponent {
  handleSubmit(e: SubmitEvent) {
    e.preventDefault()
    const data = new FormData(e.target as HTMLFormElement)
    console.log('marketing:', data.get('marketing'))
  }

  render() {
    return (
      <form onSubmit={(e) => this.handleSubmit(e)}>
        <label>
          <Switch defaultChecked={false} name="marketing" value="yes" />
          Receive marketing emails
        </label>
        <button type="submit">Save preferences</button>
      </form>
    )
  }
}

Props — Switch

PropTypeDefaultDescription
checkedbooleanControlled checked state
defaultCheckedbooleanfalseUncontrolled initial checked state
disabledbooleanfalseDisables the switch
namestringForm field name; enables form participation
valuestringValue submitted when the switch is on
onCheckedChange(checked: boolean) => voidFires when the switch state changes
classstringAdditional CSS classes
idstringHTML id attribute
childrenChildrenContent rendered inside the switch's button element (e.g. screen-reader-only text or an icon). For a visible label, wrap the Switch in your own <label> as shown above — the button is a labelable element, so clicking the label text toggles it.
aria-labelstringAccessible label when no visible label is present
aria-labelledbystringID of an element that labels the switch
aria-describedbystringID of an element that describes the switch

data-* attributes

AttributeElementWhen present
data-checkedRootThe switch is currently on
data-disabledRootdisabled is true

Keyboard navigation

KeyBehavior
SpaceToggle the switch state
EnterToggle the switch state

Accessibility

The Switch renders a <button> element with role="switch" and aria-checked reflecting the current state. When the name prop is provided, a hidden <input type="checkbox"> is rendered alongside it to participate in HTML form submission. Screen readers will announce the element as a switch with on/off state.

Unlike a Checkbox, a Switch represents an immediate action (like enabling a feature right now) rather than a form selection. If the switch controls a setting that only takes effect on form submit, consider using a Checkbox instead to set user expectations correctly.

Styling example

.morphos-switch[data-checked] {
  background: var(--morphos-color-accent);
}

.morphos-switch[data-checked]::before {
  transform: translateX(1rem);
}

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

On this page