motif svelteArc

Theme switcher ported

Four smooth ways to move between light and dark appearance.

Four smooth ways to move between light and dark appearance.

Live specimen

Loading demo…

Guidance

When to use

  • A single light and dark toggle in an app or marketing top bar.
  • Pages that want to run their own view transition from the button's position.

When not to use

  • Use user-menu when theme choice, including system, belongs inside an account menu.
  • Use theme-switch-rise for quiet product chrome, or theme-switch-eclipse for a dramatic showcase change.

Installation

pnpm dlx shadcn-svelte@latest add @arcui/theme-switch

Usage

<script lang="ts">
  import { ThemeSwitch } from '$lib/components/theme-switch';

  let theme = $state<'light' | 'dark'>('light');
</script>

<ThemeSwitch bind:theme variant="reveal" />

Variants & Examples

Default

Standard appearance and configuration.

<ThemeSwitch theme="light" variant="reveal" />

API Reference

PropTypeDefaultDescription
onThemeChange(next: Theme, variant: ThemeSwitchVariant, trigger: HTMLElement) => void–(Required) Called on press with the opposite theme, the variant, and the button, so the page transition can start from it.
labelstring–Accessible name. Defaults to \"Switch to dark mode\" or \"Switch to light mode\".
iconOnlyboolean'false'Hides the \"Switch theme\" text and renders a 38px square button.

Keyboard Interactions

KeyAction
Enter / SpaceToggles the theme.

Accessibility

  • Renders the library Button with aria-pressed set when the theme is dark.
  • aria-label defaults to "Switch to dark mode" or "Switch to light mode"; pass label to override.
  • The icons are aria-hidden.

Motion

- Sun and moon trade places with a shared rotation, scale, and blur on a snappy spring; the icon also nudges in the direction of the chosen variant. - A theme that arrives during hydration swaps without motion, so a dark page never spins its switch on load. - Reduced motion swaps the icon with an instant fade and removes the nudge; skip the page transition too when reduced.

Notes for AI

  • Use for a single light/dark toggle in a top bar. For light, dark, and system inside an account menu use user-menu.
  • The component only reports the change. Apply the theme in onThemeChange, typically inside document.startViewTransition, and use trigger's rect as the transition origin.
  • variant is passed back to onThemeChange so one handler can run the matching page transition (reveal, eclipse, split, rise).

Source of truth: registry/components/theme-switch/theme-switch.tsx