Install next-themes
pnpm i next-themes
For app router:
- Wrap
children with ThemeProvider in app/layout.tsx
- Pass
attribute="data-theme" prop to ThemeProvider
import { ThemeProvider } from "next-themes";
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode,
}>) {
return (
<html lang="en" suppressHydrationWarning>
<head>
<meta charSet="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<ThemeProvider attribute="data-theme">{children}</ThemeProvider>
</body>
</html>
);
}
- Note: If you do not add
suppressHydrationWarning to your <html> you will get warnings because next-themes updates that element. This property only applies one level deep, so it won't block hydration warnings on other elements.
Create a ThemeSwitch component for one-click theme switching
import { useTheme } from "next-themes";
const ThemeSwitch = () => {
const { resolvedTheme, setTheme } = useTheme();
const toggleTheme = (theme: string | undefined) => {
if (theme === "light") {
setTheme("dark");
} else {
setTheme("light");
}
};
return (
<div>
<button
className="cursor-pointer text-2xl"
onClick={()=> toggleTheme(resolvedTheme)}
>
{resolvedTheme === "dark" ? "🌙" : "☀️"}
</button>
</div>
);
};
export default ThemeSwitch;
Use ThemeSwitch
"use client";
import Link from "next/link";
import dynamic from "next/dynamic";
const ThemeSwitch = dynamic(() => import("./ThemeSwitch"), {
ssr: false,
loading: () => <p>...</p>,
});
export const Header = () => {
return (
<header className="border-b border-dashed border-black dark:border-white flex justify-between items-center p-5">
<div>
<Link href="/">
<h1 className="text-2xl">The Cosmo Nomad</h1>
</Link>
</div>
<ThemeSwitch />
</header>
);
};
For Tailwind 4.1 and above, add this to global CSS:
@import "tailwindcss";
@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));
Use the dark: prefix for Tailwind utility classes to apply them in dark mode
className = "border-b border-dashed border-black dark:border-white";
References