Theme Toggle

Light/dark mode toggle switch with smooth animation. Uses the ThemeProvider context for global theme management.

Interactive Demo

Click the toggle to switch between light and dark themes. The entire design library will respond to the change.

tsx
<ThemeToggle />

Design Details

52px × 28px

Dimensions

52px wide × 28px tall, 24px knob

Animation

Spring physics for knob slide (stiffness: 500, damping: 30)

Icons

Custom Sun and Moon SVG icons, 14px

Colors

Uses --toggle-bg, --toggle-knob-bg, --toggle-icon-active/inactive

SSR Safe

Hydration Safe Implementation

The component uses useSyncExternalStore to safely detect client-side rendering, avoiding hydration mismatches. A placeholder is rendered during SSR that matches the client state.

Theme Provider

The toggle requires the ThemeProvider context. It's already included in the root layout.

tsx
// Root layout already includes this
import { ThemeProvider } from '@/lib/theme'

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <ThemeProvider>
          {children}
        </ThemeProvider>
      </body>
    </html>
  )
}

Using Theme Context

Access theme state programmatically with the useTheme hook:

tsx
import { useTheme } from '@/lib/theme'

function MyComponent() {
  const { theme, resolvedTheme, setTheme } = useTheme()

  // theme: 'light' | 'dark' | 'system'
  // resolvedTheme: 'light' | 'dark' (actual applied theme)
  // setTheme: (theme) => void

  return (
    <button onClick={() => setTheme('dark')}>
      Go Dark
    </button>
  )
}

Props

PropTypeDefaultDescription
classNamestring-Additional CSS classes

Import

tsx
import { ThemeToggle } from '@/components/ui/ThemeToggle'
import { useTheme } from '@/lib/theme'