Motoko UI Released — Explore the components

Theme Switcher

Lightweight light/dark control — icon, toggle, and segmented variants with smooth CSS motion.

Icon

Toggle

Segmented

Installation

pnpm dlx shadcn@latest add @motokoui/theme-switcher

This installs next-themes and lucide-react if they are not already in your project.

Setup

Wrap your app with ThemeProvider once (usually in the root layout). Use the class strategy so Motoko / Tailwind dark: variants work:

import { ThemeProvider } from "@/components/ui/theme-switcher"
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body>
        <ThemeProvider attribute="class" defaultTheme="system" enableSystem>
          {children}
        </ThemeProvider>
      </body>
    </html>
  )
}

Make sure your CSS defines light tokens on :root and dark overrides under .dark (same pattern as shadcn).

Usage

import { ThemeSwitcher } from "@/components/ui/theme-switcher"
 
export default function Example() {
  return <ThemeSwitcher />
}

Variants

<ThemeSwitcher variant="icon" />
<ThemeSwitcher variant="toggle" />
<ThemeSwitcher variant="segmented" />

With system preference

<ThemeSwitcher
  variant="segmented"
  themes={["light", "dark", "system"]}
  showLabels
/>

Controlled

"use client"
 
import * as React from "react"
 
import { ThemeSwitcher, type ThemeMode } from "@/components/ui/theme-switcher"
 
export default function ControlledExample() {
  const [theme, setTheme] = React.useState<ThemeMode>("system")
 
  return (
    <ThemeSwitcher variant="segmented" value={theme} onThemeChange={setTheme} />
  )
}

Props

ThemeSwitcher

PropTypeDefault
variant"icon" | "toggle" | "segmented""icon"
themes("light" | "dark" | "system")[]["light","dark"] / segmented: + "system"
value"light" | "dark" | "system"
defaultValue"light" | "dark" | "system"
onThemeChange(theme: ThemeMode) => void
size"sm" | "default" | "lg""default"
disableAnimationbooleanfalse
showLabelsbooleanfalse
labelsPartial<Record<ThemeMode, string>>
classNamestring
disabledbooleanfalse

ThemeProvider

Re-export of next-themes ThemeProvider. Common props:

PropTypeNotes
attributestringUse "class" for Motoko / Tailwind dark
defaultThemestringe.g. "system"
enableSystembooleanFollow OS preference when theme is system
disableTransitionOnChangebooleanOptional; skips CSS flash on theme change

Notes

  • Animations are CSS-only (cubic-bezier(0.2, 0, 0, 1)) — no motion dependency.
  • Icon swap uses opacity / scale / blur cross-fade so enter and exit stay interruptible.
  • A short skeleton renders until mount to avoid hydration mismatch with next-themes.