# <motion-theme-toggle>

Light / dark mode control with an optional third "system" option. Applies
`data-theme` and `color-scheme` to a target element, follows the OS
preference, optionally remembers the choice, and can reveal the new theme
with a circular view-transition wipe from the control. API-compatible with
Google Chrome Labs' `dark-mode-toggle`.

**Use it for:** letting people choose a light or dark theme, or follow the
system setting, for a whole site or for one part of a page.

**Avoid it for:** sites with only one theme, and other on/off settings;
use a native checkbox for those. To only show the current theme as an
icon, use `motion-theme-icon`.

**Accessibility:** `icon` and `switch` render a button with
`role="switch"`, where checked means dark. With `system`, `icon` is a plain
button whose label names the current mode, and each press moves to the
next mode. `toggle` is a native radio group in a `<fieldset>`; with
`icon-only` the labels stay available to screen readers. `menu` is a menu
button: the Up and Down arrow keys open it and move between items, Home
and End jump to the first and last item, and Escape closes it and returns
focus to the button. Without `legend` the name is "Dark" for `icon` and
`switch`, and "Theme" for `toggle` and `menu`, so set `legend` to a clear
name.

**Reduced motion:** the theme changes at once and `wipe` is skipped. The
icon, the selection marker, the switch thumb and the menu change with no
animation, and the hover and press effects are off.

**Common mistakes:** writing dark styles only in a
`prefers-color-scheme: dark` media query; the toggle cannot change that
query, so style `[data-theme="dark"]` on the target. Relying on the
component alone to apply a saved theme; it applies the theme only after it
loads, so add a small inline script in `<head>` to avoid a flash of the
wrong theme.

Docs: https://www.motion-components.dev/docs/components/motion-theme-toggle/

## Install

```js
import 'motion-components/motion-theme-toggle'
```

Or without a build step:

```html
<script type="module" src="https://cdn.jsdelivr.net/npm/motion-components@1/dist/motion-theme-toggle.js/+esm"></script>
```

## Example

```html
<motion-theme-toggle permanent></motion-theme-toggle>
<motion-theme-toggle appearance="menu" system></motion-theme-toggle>
<motion-theme-toggle wipe></motion-theme-toggle>
```

## Attributes

| Attribute | Type | Default | Description |
| --- | --- | --- | --- |
| `mode` | `'light' \| 'dark' \| 'system'` | `'light'` | Selected mode: `'light'`, `'dark'`, or `'system'` (requires `system`). Defaults to the OS preference. |
| `appearance` | `'icon' \| 'toggle' \| 'switch' \| 'menu'` | `'icon'` | Visual style: `'icon'`, `'toggle'` (segmented), `'switch'`, or `'menu'` (drop-down). |
| `system` | `boolean` | `false` | Offers a third "system" option that follows the OS preference. Ignored by `switch`. |
| `permanent` | `boolean` | `false` | Remembers the choice in `localStorage` (`motion-theme`, or `motion-theme:<target>` for other targets) and restores it on load. |
| `legend` | `string` | `''` | Group label. Used as the accessible name of `icon`, `switch` and `menu`. |
| `light` | `string` | `'Light'` | Label of the light option. |
| `dark` | `string` | `'Dark'` | Label of the dark option. |
| `system-label` | `string` | `'System'` | Label of the system option. |
| `remember` | `string` | `''` | When set, shows a checkbox with this label that toggles `permanent`. |
| `target` | `string` | `'html'` | CSS selector of the element that receives `data-theme` and `color-scheme`. |
| `wipe` | `boolean` | `false` | Reveals the new theme with a circular view-transition wipe from the control. Off by default. |
| `icon-only` | `boolean` | `false` | Hides the option labels of the `toggle` appearance and shows icons only. Labels stay available to screen readers and as tooltips. |
| `duration` | `number` | `0.5` | Spring duration of the icon morph and wipe, in seconds. |
| `bounce` | `number` | `0.25` | Spring bounciness of the icon morph and controls. |

## Events

The `motion-*` events bubble and are composed.

| Event | Description |
| --- | --- |
| `colorschemechange` | When the mode or applied color scheme changes. `detail: { colorScheme, mode }`. |
| `permanentcolorschemechange` | When `permanent` changes. `detail: { permanent }`. |

## CSS custom properties

| Property | Description |
| --- | --- |
| `--mc-theme-toggle-surface` | Background of the switch track, segmented group and menu trigger. |
| `--mc-theme-toggle-border` | Border color of the controls. |
| `--mc-theme-toggle-accent` | Selected segment, switch thumb and active menu item background. |
| `--mc-theme-toggle-menu-bg` | Drop-down menu background. Default `Canvas`. |
| `--mc-theme-toggle-radius` | Corner radius of the controls. Default `999px`. |
| `--mc-theme-icon-size` | Icon size. Default `1.25em`. |

## CSS parts

| Part | Description |
| --- | --- |
| `button` | The icon button (`icon`) or menu trigger (`menu`). |
| `track` | The switch track (`switch`). |
| `thumb` | The switch thumb (`switch`). |
| `segment` | Each option of the segmented group (`toggle`). |
| `menu` | The drop-down panel (`menu`). |
| `item` | Each drop-down option (`menu`). |
