"use client"; import { useEffect, useState } from "react"; import { useTheme } from "next-themes"; import { Moon, Sun, Monitor } from "lucide-react"; import { Button } from "@/components/ui/button"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; export function ThemeToggle() { const { setTheme, theme } = useTheme(); // next-themes can't read the stored theme on the server, so SSR // always sees `theme === undefined`. Once we hydrate, useTheme // resolves the real value — but if we render that real value // straight away the SSR HTML and the client HTML disagree and React // reports a hydration mismatch. Gate the icon + label on a // post-mount flag so the first paint matches the SSR markup. const [mounted, setMounted] = useState(false); useEffect(() => setMounted(true), []); const effectiveTheme = mounted ? theme : undefined; const Icon = effectiveTheme === "dark" ? Moon : effectiveTheme === "light" ? Sun : Monitor; const label = effectiveTheme ?? "system"; return ( setTheme("light")}> Light setTheme("dark")}> Dark setTheme("system")}> System ); }