Theme Toggle

A ready-made light/dark switch built on Button, with a cross-fading sun and moon.

Import#

import { ThemeToggle } from "astralis-ui";

Usage#

Drop it anywhere inside an AstralisProvider — it reads and writes the theme through the same context the whole library uses, and persists the choice to localStorage. Every demo on this page is live: clicking one switches this site's theme, and the icon rotates a quarter turn as sun and moon cross-fade.

The one in this site's header is this exact component.

With a label#

showLabel adds a text label that names the mode a click switches to. Sizing follows Button's scale, and the icon scales with it.

Variants#

Theme Toggle extends Button, so every variant, colorScheme, size and rounded value works.

Reading the theme yourself#

For custom controls, the same context is available via the useTheme hook:

import { useTheme } from "astralis-ui";

function CustomSwitch() {
  const { theme, resolvedTheme, setTheme } = useTheme();
  // theme: "light" | "dark" | "system" — the user's setting
  // resolvedTheme: "light" | "dark" — what's actually applied
  return (
    <button onClick={() => setTheme(resolvedTheme === "dark" ? "light" : "dark")}>
      Switch to {resolvedTheme === "dark" ? "light" : "dark"}
    </button>
  );
}

Props#

Theme Toggle accepts every Button prop except children and onClick (it owns both). The most relevant:

PropTypeDefaultDescription
showLabelbooleanfalseShows a text label next to the icon — “Light Mode” or “Dark Mode”, reflecting what a click switches to.
variant"solid" | "subtle" | "surface" | "outline" | "text" | "link""outline"Inherited from Button — every Button variant works.
size"xs" | "sm" | "md" | "lg" | "xl""md"Inherited from Button; the icon scales with it.

Accessibility#

  • Without a label it carries aria-label="Toggle theme" automatically; with showLabel the visible text is the accessible name.
  • Must be rendered inside an AstralisProvideruseTheme throws otherwise.