Command Palette

Search for a command to run...

1.7k

Command Palette

Search for a command to run...

Blog

Theme Toggle Effect

Animated transitions when switching between light and dark themes.

Loading…
"use client"
 
import { MoonIcon, SunMediumIcon } from "lucide-react"
import { useTheme } from "next-themes"
 
import { Button } from "@/components/ui/button"
 
import { ThemeToggleEffectSelector } from "./theme-toggle-effect-selector"
 
export default function ThemeToggleEffectDemo() {
  const { resolvedTheme, setTheme } = useTheme()
 
  const switchTheme = () => {
    setTheme(resolvedTheme === "dark" ? "light" : "dark")
  }
 
  const handleThemeToggleClick = () => {
    if (!document.startViewTransition) switchTheme()
    else document.startViewTransition(switchTheme)
  }
 
  return (
    <div className="flex gap-2">
      <ThemeToggleEffectSelector />
 
      <Button
        variant="outline"
        size="icon"
        aria-label="Theme Toggle"
        onClick={handleThemeToggleClick}
      >
        <MoonIcon className="hidden [html.dark_&]:block" />
        <SunMediumIcon className="hidden [html.light_&]:block" />
      </Button>
    </div>
  )
}

Browser Compatibility

This component uses the View Transitions API. Check the latest browser compatibility on MDN before using in production.

Installation

Circle

$ pnpm dlx shadcn@latest add @ncdai/theme-toggle-effect-circle

Circle Blur

$ pnpm dlx shadcn@latest add @ncdai/theme-toggle-effect-circle-blur

Circle Blur (Top Left)

$ pnpm dlx shadcn@latest add @ncdai/theme-toggle-effect-circle-blur-top-left

Polygon

$ pnpm dlx shadcn@latest add @ncdai/theme-toggle-effect-polygon

Polygon Gradient

$ pnpm dlx shadcn@latest add @ncdai/theme-toggle-effect-polygon-gradient

Usage

Wrap your theme setter with document.startViewTransition to trigger the effect:

const { setTheme } = useTheme()
 
function toggleTheme(theme: string) {
  if (!document.startViewTransition) {
    setTheme(theme)
    return
  }
 
  document.startViewTransition(() => setTheme(theme))
}

References