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>
  )
}

oh I love this one, have to implement it on orcdev.com

OrcDev
OrcDev
Creator of 8bitcn.com

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