Split

The next appearance opens from a slim center seam.

pnpm dlx shadcn@latest add @uiarc/theme-switch-split
Try the transition
  • Centered layouts where the theme should open symmetrically from a middle seam.
  • Pages where the switch position varies, since the split does not depend on where the button sits.
  • Use theme-switch for a reveal that grows from the button itself.
  • Use theme-switch-rise for the calmest option in product UI.

Installation

Add Split with the shadcn CLI, or copy the source by hand.

pnpm dlx shadcn@latest add @uiarc/theme-switch-split

Adds the component and its local dependencies, and installs motion, lucide-react. First time? Add the @uiarc registry to components.json, or use the full URL:

example.tsx
import { ThemeSwitch } from "@/registry/components/theme-switch/theme-switch"; <ThemeSwitch  theme={theme}  variant="split"  onThemeChange={(next, variant, trigger) => runThemeTransition(next, variant, trigger)}/>

Examples

3 more in theme. Each has its own page with install and API details.

Theme switcher

Four smooth ways to move between light and dark appearance.

Open page

Eclipse

The next appearance crosses the page like an eclipse.

Open page

Rise

The next appearance rises into place.

Open page

ThemeSwitch

A secondary Button that swaps a sun and moon icon and reports the next theme. The page transition itself is yours to run.

PropTypeDefaultDescription
themeRequired"light" | "dark"–The current theme. Drives the icon and aria-pressed.
onThemeChangeRequired(next: Theme, variant: ThemeSwitchVariant, trigger: HTMLElement) => void–Called on press with the opposite theme, the variant, and the button, so the page transition can start from it.
variant"reveal" | "eclipse" | "split" | "rise""reveal"Names the page transition and sets the small icon nudge that matches it.
labelstring–Accessible name. Defaults to "Switch to dark mode" or "Switch to light mode".
iconOnlybooleanfalseHides the "Switch theme" text and renders a 38px square button.
EnterorSpace
Toggles the theme.
  • Same button as theme-switch: aria-pressed reflects dark mode and the label names the next theme.
  • Keep the split reveal off for reduced motion and swap the theme directly.
  • variant="split": the next appearance opens from a slim center seam; run it in onThemeChange with a view transition.
  • The icon shifts 1px right in dark mode.
  • Reduced motion removes the nudge and swaps the icon with a fade.
  • The labelled button fits a desktop top bar; pass iconOnly for a fixed 38px square on narrow headers and mobile.
  • Hover styles apply only on hover-capable fine pointers, so touch taps do not leave a stuck hover state.
  • The button itself is tiny: one icon swap on a spring, and the first theme after hydration applies without animating.
  • The page transition is yours; a full-page view transition snapshots the whole document, so keep it short and skip it for reduced motion.

Notes for AI

Give your coding assistant the Markdown reference instead of screenshots.

  • Select with variant="split". The prop only styles the icon nudge and is passed back to onThemeChange; the page animation is your code.
  • Split is symmetric and does not depend on where the button sits, so it suits centered layouts.

The full library index for assistants is at /llms.txt.