ThemeSwitcher

Appearance mode controller providing zero-layout-shift switching between light, dark, and system color schemes, complete with a FOUC-prevention hydration script and useTheme hook.

// Radix — @radix-ui/react-dropdown-menu
import { ThemeScript, ThemeSwitcher } from "@shavin/ui";

Variants

ThemeSwitcher offers 4 purpose-built variants: icon-button (cycles through modes), segmented (3-way selector), menu (Radix dropdown), and switch (binary toggle).

Icon Button
Segmented
Menu
Switch
{/* 1. Icon Button (Default) */}
<ThemeSwitcher variant="icon-button" />

{/* 2. Segmented 3-Way Control */}
<ThemeSwitcher variant="segmented" showLabels />

{/* 3. Dropdown Menu */}
<ThemeSwitcher variant="menu" showLabels />

{/* 4. Binary Switch */}
<ThemeSwitcher variant="switch" />

Sizes

<ThemeSwitcher variant="segmented" size="sm" showLabels />
<ThemeSwitcher variant="segmented" size="md" showLabels />
<ThemeSwitcher variant="segmented" size="lg" showLabels />

FOUC Prevention with ThemeScript

To eliminate the flash of unstyled theme during initial page load, place ThemeScript inside your root layout head:

// app/layout.tsx
import { ThemeScript } from "@shavin/ui";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en" suppressHydrationWarning>
      <head>
        <ThemeScript />
      </head>
      <body>{children}</body>
    </html>
  );
}

useTheme Hook

Directly access or control the active theme programmatically with the useTheme() hook:

import { useTheme } from "@shavin/ui";

export function CustomToggle() {
  const { theme, resolvedTheme, setTheme, toggleTheme } = useTheme();

  return (
    <button onClick={toggleTheme}>
      Current theme: {theme} (active: {resolvedTheme})
    </button>
  );
}

Props

PropTypeDefault
variant"icon-button" | "segmented" | "menu" | "switch"
storageKeystring
defaultThemeThemeMode
showLabelsboolean
labels{
lightstring
darkstring
systemstring
size"sm" | "md" | "lg""md"
Configure Theme
Theme
Accent Color
Custom
Gray Family
Appearance
Radius
Scaling
Panel Style
Heading Font
Body Font