quadratic/ui

Dark Mode

Quickly set up dark mode using next-themes.

Install the next-themes package.

pnpm add next-themes

Edit your root layout.tsx file to include the ThemeProvider component.

import "~/styles/globals.css";

import { ThemeProvider } from "next-themes";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en" suppressHydrationWarning>
      <head />
      <body>
        <ThemeProvider
          defaultTheme="dark"
          attribute="class"
          disableTransitionOnChange
        >
          <Header />
          <main>{children}</main>
        </ThemeProvider>
      </body>
    </html>
  );
}

Add your theme toggle component. Mine looks like this.

import { useTheme } from "next-themes";
import { MoonIcon, SunIcon } from "@radix-ui/react-icons";

import { Button } from "~/components/ui/Button";

export default function ThemeToggle() {
  const { theme, setTheme } = useTheme();

  const Icon = theme === "light" ? SunIcon : MoonIcon;

  return (
    <Button
      onClick={()=> setTheme(theme= "light" ? "dark" : "light")}
      variant="ghost"
      subject="icon"
      size="xs"
      className="text-muted-foreground [&_svg]:size-4.5"
    >
      <Icon />
    </Button>
  );
}

Import the ThemeToggle using next/dynamic. Learn why you need to do this here.

import { dynamic } from "next/dynamic";

const ThemeToggle = dynamic(() => import("./ThemeToggle"), {
  ssr: false,
  loading: () => <div className="size-8" />,
});

export default function Header() {
    return (
        <>
            ...
            <ThemeToggle />
            ...
        </>
    )
}