---
## ThemeSwitcher
Cycles between light, dark, and system color schemes. Sets a
`light`/`dark` class on the `` element for explicit choices and clears
it in system mode (so the CSS `light-dark()` function follows the OS natively).
Persists the choice to `localStorage` where that is usable, and never throws
where it is not: with storage switched off (a hardened browser profile, an
embedded webview) or a quota refusing the write, the button still switches the
theme and the choice simply does not survive a reload. So treat persistence as
best-effort — do not build a flow that depends on the stored key existing.
The button's accessible name and tooltip always name the current theme, so it
takes no `aria-label` or `title`.
**Import:** `import { ThemeSwitcher } from '@urbicon-ui/blocks';`
### Examples
```svelte
```
```svelte
```
### Variants
- variant: filled, ghost, outlined (default: ghost)
- size: lg, md, sm (default: md)
- disabled: true (default: false)
### Api
| Prop | Type | Required | Default | Description |
| --- | --- | :---: | --- | --- |
| ...HTMLButtonAttributes | `HTMLAttributes` | no | | HTML attributes (excluding: 'class' | 'children' | 'disabled' | 'type' | 'aria-label' | 'title') |
| class | `string` | no | | Additional CSS classes. In the same Tailwind bucket `class` wins over the `slotClasses` entry for the element it lands on. Presets and provider defaults sit below both. |
| disabled | `boolean` | no | | Disable the switcher. |
| onThemeChange | `(theme: Theme) => void` | no | | Called after the theme changes. |
| preset | `string` | no | | Apply a named preset registered via ``. Prefer this over `class` overrides when the requested look falls outside the semantic intent palette — presets keep hover/active/dark-mode logic coherent and make the custom look reusable across the project. |
| size | `ThemeSwitcherVariants['size']` | no | 'md' | Button size. |
| slotClasses | `Partial>` | no | | Per-slot class overrides. In the same Tailwind bucket `class` wins over the `slotClasses` entry for the element it lands on. Presets and provider defaults sit below both. |
| storageKey | `string | false` | no | 'urbicon-theme' | `localStorage` key holding the choice, or `false` to switch persistence off. A stored value is read once on mount; `'system'` is persisted as the ABSENCE of the key, so the OS keeps winning after a reload. Where storage is unusable nothing is written and nothing throws — the theme is back to `'system'` on the next load. |
| strategy | `'cycle' | 'toggle'` | no | 'cycle' | Interaction mode. - `'cycle'` — single button cycling light → dark → system (default) - `'toggle'` — single button toggling light ↔ dark (no system option) |
| theme | `Theme` | no | 'system' | Current theme. Supports `bind:theme`. |
| unstyled | `boolean` | no | false | Strip all default styles. |
| variant | `ThemeSwitcherVariants['variant']` | no | 'ghost' | Visual style of the button. |
Inherited from:
- Omit<
HTMLButtonAttributes,
'class' | 'children' | 'disabled' | 'type' | 'aria-label' | 'title'
> (omit-pattern)
### Types
```ts
type Theme = 'light' | 'dark' | 'system'
```
```ts
type SlotNames = keyof ReturnType & string
```
```ts
type VariantProps = Omit<
Exclude[0], undefined>,
'class'
>
```
### Slots (slotClasses keys)
`button`, `icon`