---
title: Switch
description: Toggle switch control with icon slots and loading state.
sidebar:
  order: 9
search:
  tags: [toggle, boolean, checked, setting]
---

# Switch

> Toggle switch control with icon slots and loading state.

## Import

```tsx
import { Switch } from 'moraine'
```

## Slot Structure

Toggle track with thumb and optional label area.

```text
root
├── container
│   ├── input
│   └── track
│       └── thumb
└── wrapper (optional)
    ├── label (optional)
    └── description (optional)
```

## Examples

### Basic + Controlled

Uncontrolled and controlled switch with icon slots.

```tsx
function BasicControlled() {
  const [checked, setChecked] = createSignal(false)

  return (
    <div class="flex flex-col gap-3 max-w-xl">
      <Switch
        label="Email alerts"
        description="Uncontrolled"
        defaultChecked
        checkedIcon="i-lucide-bell"
        uncheckedIcon="i-lucide-bell-off"
      />
      <Switch
        label="Deploy protection"
        description={`Current: ${checked() ? 'enabled' : 'disabled'}`}
        checked={checked()}
        onChange={setChecked}
        checkedIcon="i-lucide-shield-check"
        uncheckedIcon="i-lucide-shield"
      />
    </div>
  )
}
```

### Variants

Loading, disabled, and explicit icon combinations.

```tsx
function Variants() {
  return (
    <div class="flex flex-col gap-3 max-w-xl">
      <Switch
        label="Sync in progress"
        description="Loading state"
        loading
        checked
        checkedIcon="i-lucide-check"
        uncheckedIcon="i-lucide-x"
      />
      <Switch
        label="Dark mode"
        description="Custom icons"
        defaultChecked
        checkedIcon="i-lucide-moon-star"
        uncheckedIcon="i-lucide-sun"
      />
      <Switch
        label="Billing lock"
        description="Disabled"
        disabled
        checked
        checkedIcon="i-lucide-lock"
        uncheckedIcon="i-lucide-unlock"
      />
    </div>
  )
}
```

### Sizes

Switch size scale from xs to xl.

```tsx
function Sizes() {
  const SIZES: SwitchSizeName[] = ['xs', 'sm', 'md', 'lg', 'xl']

  type SwitchSizeName = Exclude<SwitchT.Variant['size'], undefined>

  return (
    <div class="gap-3 grid sm:grid-cols-2">
      <For each={SIZES}>
        {(size) => (
          <Switch
            size={size}
            label={`Size ${size}`}
            description="Size preview"
            defaultChecked={size === 'lg' || size === 'xl'}
          />
        )}
      </For>
    </div>
  )
}
```

### Custom True/False Values

Map checked state to domain values instead of boolean.

```tsx
function CustomTrueFalseValues() {
  const [deploymentGuard, setDeploymentGuard] = createSignal<'enabled' | 'disabled'>('disabled')

  return (
    <div class="max-w-xl space-y-3">
      <Switch<'enabled', 'disabled'>
        label="Deployment gate"
        description="Domain value binding"
        trueValue="enabled"
        falseValue="disabled"
        checked={deploymentGuard()}
        onChange={setDeploymentGuard}
        checkedIcon="i-lucide-check-check"
        uncheckedIcon="i-lucide-x"
      />
      <p class="text-xs text-muted-foreground">Current value: {deploymentGuard()}</p>
    </div>
  )
}
```

## API Reference

### Attributes

#### `root`

Switch wrapper that coordinates input, track, thumb, and text content.

#### `track`

Visible switch track that shows checked and unchecked state.

##### Data Attributes

| Attribute | Type | Description |
| --- | --- | --- |
| data-checked | string \| undefined | Present when the item is checked or selected. |
| data-disabled | string \| undefined | Present when the component or item is disabled. |
| data-invalid | string \| undefined | Present when the field has a validation error. |
| data-readonly | string \| undefined | Present when the field is read-only. |

##### ARIA Attributes

| Attribute | Type | Description |
| --- | --- | --- |
| aria-checked | boolean \| string \| undefined | Accessibility attribute forwarded by the rendered component. |
| aria-disabled | boolean \| string \| undefined | Indicates that the control is disabled. |
| aria-labelledby | boolean \| string \| undefined | References the element that labels the control or region. |
| aria-readonly | boolean \| string \| undefined | Indicates that the control value cannot be changed by the user. |
| aria-required | boolean \| string \| undefined | Indicates that user input is required. |
| role | string | Defines the semantic role exposed to assistive technology. |

#### `thumb`

Movable knob inside the switch track.

##### Data Attributes

| Attribute | Type | Description |
| --- | --- | --- |
| data-checked | string \| undefined | Present when the item is checked or selected. |
| data-disabled | string \| undefined | Present when the component or item is disabled. |
| data-readonly | string \| undefined | Present when the field is read-only. |

#### `icon`

Checked, unchecked, or loading icon rendered inside the thumb.

#### `wrapper`

Inner layout wrapper used by switch list and card variants.

#### `label`

Primary switch label text.

#### `description`

Supporting text associated with the switch.

### Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| checked | TTrue \| TFalse \| undefined | — | Whether the switch is checked. |
| checkedIcon | IconT.Name | — | Icon shown when the switch is checked. |
| class | ClassValue | — | Class applied to the component root or trigger element. |
| classes | SwitchT.Classes \| undefined | — | — |
| defaultChecked | boolean \| undefined | — | Whether the switch is checked by default. |
| description | JSX.Element | — | Description for the switch. |
| disabled | boolean \| undefined | false | Whether the input is disabled. |
| falseValue | TFalse \| undefined | false | Value to use when the switch is unchecked. |
| id | string \| undefined | — | The ID of the input element. |
| label | JSX.Element | — | Label for the switch. |
| loading | boolean \| undefined | false | Whether the switch is in a loading state. |
| loadingIcon | IconT.Name | icon-loading | Icon shown during loading state. |
| name | string \| undefined | — | The name of the input element, used for form submission. |
| onChange | ((value: TTrue \| TFalse) => void) \| undefined | — | Callback when the switch state changes. |
| onPointerDown | JSX.EventHandlerUnion<HTMLButtonElement, PointerEvent> \| undefined | — | Pointer down handler for the switch root container. |
| readOnly | boolean \| undefined | false | Whether the input is read-only. |
| ref | JSX.HTMLElementTags["div"] extends { ref?: infer Ref; } ? Ref : never \| undefined | — | — |
| required | boolean \| undefined | false | Whether the input is required. |
| size | "xs" \| "sm" \| "md" \| "lg" \| "xl" \| undefined | — | — |
| style | JSX.CSSProperties \| undefined | — | — |
| styles | SwitchT.Styles \| undefined | — | — |
| trueValue | TTrue \| undefined | true | Value to use when the switch is checked. |
| uncheckedIcon | IconT.Name | — | Icon shown when the switch is unchecked. |
| value | string \| undefined | on | Native value submitted when the switch is checked. |

### ARIA

Accessibility attributes and roles emitted by the component markup.

| Attribute | Type | Description |
| --- | --- | --- |
| aria-checked | boolean \| string \| undefined | Accessibility attribute forwarded by the rendered component. |
| aria-disabled | boolean \| string \| undefined | Indicates that the control is disabled. |
| aria-hidden | boolean \| string \| undefined | Hides decorative content from assistive technology. |
| aria-labelledby | boolean \| string \| undefined | References the element that labels the control or region. |
| aria-readonly | boolean \| string \| undefined | Indicates that the control value cannot be changed by the user. |
| aria-required | boolean \| string \| undefined | Indicates that user input is required. |
| role | string | Defines the semantic role exposed to assistive technology. |

### Data Attributes

State and slot attributes exposed for styling hooks and selectors.

| Attribute | Type | Description |
| --- | --- | --- |
| data-checked | string \| undefined | Present when the item is checked or selected. |
| data-disabled | string \| undefined | Present when the component or item is disabled. |
| data-invalid | string \| undefined | Present when the field has a validation error. |
| data-loading | string \| undefined | Present when the component is loading. |
| data-readonly | string \| undefined | Present when the field is read-only. |
| data-slot | string | Identifies the rendered slot for styling hooks and selectors. |
| data-unchecked | string \| undefined | State or slot attribute exposed for styling hooks and selectors. |
