JGuang

Switch

Switch · Astryx

Preview
npm install @astryxdesign/core@0.7.1 @astryxdesign/theme-neutral@0.7.1 @stylexjs/stylex@0.19.0

Switch

A toggle control for on/off states that take effect immediately. Supports labels, descriptions, loading states, and validation. Use it for settings or preferences that apply instantly. For changes requiring a form submission, use a checkbox instead.

Installation

npm install @astryxdesign/core@0.7.1 @astryxdesign/theme-neutral@0.7.1 @stylexjs/stylex@0.19.0

Requires React 19+, base CSS and a Theme provider. See Setup.

Switch

A toggle control for on/off states that take effect immediately. Supports labels, descriptions, loading states, and validation. Use it for settings or preferences that apply instantly. For changes requiring a form submission, use a checkbox instead.

PropTypeDefaultDescription
refReact.Ref<HTMLInputElement>Ref forwarded to the underlying <input> element.
label *stringLabel text for the switch (always rendered for accessibility).
value *booleanWhether the switch is on or off.
onChange(checked: boolean, e: ChangeEvent<HTMLInputElement>) => voidCallback fired when the switch state changes.
changeAction(checked: boolean, e: ChangeEvent<HTMLInputElement>) => void | Promise<void>Async action fired after onChange. Triggers optimistic UI and shows a loading spinner until the promise resolves.
isLoadingbooleanfalseWhether the switch is in a loading state, showing a spinner inside the thumb.
isLabelHiddenbooleanfalseVisually hides the label while keeping it accessible to screen readers.
descriptionstringDescription text displayed below the label.
isDisabledbooleanfalseWhether the switch is disabled.
size'sm' | 'md''md'Size variant controlling track and thumb dimensions. sm (32x20px) matches sm checkbox/radio vertical rhythm; md (40x24px, default) matches md checkbox/radio vertical rhythm.
htmlNamestringThe HTML name attribute for the underlying checkbox input, useful for form submissions (submits "on" when the switch is on).
disabledMessagestringExplains why the switch is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the switch focusable via aria-disabled (toggling stays blocked). Use this instead of wrapping a disabled Switch in Tooltip. Disabled controls swallow the hover events an external Tooltip needs.
isOptionalbooleanfalseWhether the field is optional. Mutually exclusive with isRequired.
isRequiredbooleanfalseWhether the switch is required. Mutually exclusive with isOptional.
status{type: 'warning' | 'error' | 'success', message?: string}Status indicator with type and message. Displays a colored message box below the switch and sets aria-invalid when type is "error".
onFocus(e: FocusEvent<HTMLInputElement>) => voidCallback fired when the switch receives focus.
onBlur(e: FocusEvent<HTMLInputElement>) => voidCallback fired when the switch loses focus.
labelIconIconTypeIcon displayed before the label text. See astryx docs icons for valid semantic names.
labelTooltipstringTooltip text shown in an info icon at the end of the label.
labelPosition'start' | 'end''end'Which side of the switch the label appears on. "start" places the label before the switch.
labelSpacing'hug' | 'spread''hug'Spacing behavior between label and switch. "hug" places them next to each other; "spread" pushes them to opposite ends of the container (full width).
widthSizeValueWidth of the field (number = pixels, string used as-is, e.g. "100%"). Sizes the whole field (label, control, and status) so they stay aligned.

Usage guidance

  • Use for settings that apply immediately; the toggle should take effect without a separate save action.
  • Pair with a clear, concise label that describes the setting being controlled.
  • Avoid: Use for options that require a form submission to take effect; use a checkbox instead.
  • Avoid: Use a switch for multi-state values; it's strictly on/off.
  • Avoid: Wrap a disabled switch in Tooltip to explain why it is disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.

Theming API

{
  "targets": [
    {
      "className": "astryx-switch",
      "visualProps": [
        "size"
      ],
      "states": [
        "checked",
        "disabled"
      ]
    },
    {
      "className": "astryx-switch-thumb",
      "visualProps": [
        "size"
      ],
      "states": [
        "checked"
      ]
    },
    {
      "className": "astryx-switch-field",
      "visualProps": [
        "labelPosition",
        "labelSpacing"
      ]
    },
    {
      "className": "astryx-switch-label"
    }
  ]
}

Accessibility

  • Track and thumb: The on and off tracks must each have at least 3:1 contrast with the surface behind them, and the thumb with its track. For Hover and Pointer down, measure the final colors after the tint and the pressed overlay are applied. — 3:1

Anatomy

  • Field: Container arranging the switch, label, and feedback.
  • Track: Pill-shaped surface that shows the off or on state.
  • Thumb: Indicator that moves across the track when state changes.
  • Label: Text identifying the setting controlled by the switch.
  • Description: Helper text below the label.
  • Spinner: Loading indicator shown inside the thumb while busy.
  • Status message: Error, warning, or success message below the switch.

Examples

  • Switch: A toggle switch for enabling notifications.
  • Switch — Disabled: Disabled switch with label and description for gated features.
  • Switch — Settings Panel: Settings panel with spread-spaced switches in a card.
  • Switch — With Description: Toggle with a label and supporting description text.
  • Switch — With Status: Switches with error, warning, and success validation states.