Capítulo 79 de 108

Dark Mode (Next.js)

Core Idea

Adiciona dark mode a um app Next.js usando a lib next-themes, que gerencia classe CSS, persistência e prevenção de flash de tema incorreto.

Key Concepts

  • next-themes: lib externa que expõe ThemeProvider e useTheme().
  • suppressHydrationWarning: obrigatório na tag <html> porque o tema é aplicado client-side, causando mismatch esperado entre SSR e hydration.
  • attribute="class": next-themes alterna a classe dark no <html> (compatível com o Tailwind dark: variant).
  • defaultTheme="system" / enableSystem / disableTransitionOnChange: props padrão recomendadas.

Code Examples

"use client"
import * as React from "react"
import { ThemeProvider as NextThemesProvider } from "next-themes"

export function ThemeProvider({ children, ...props }: React.ComponentProps<typeof NextThemesProvider>) {
  return <NextThemesProvider {...props}>{children}</NextThemesProvider>
}
  • O que demonstra: Wrapper client-side em torno do provider da lib (necessário por Server Components).
<html lang="en" suppressHydrationWarning>
  <body>
    <ThemeProvider attribute="class" defaultTheme="system" enableSystem disableTransitionOnChange>
      {children}
    </ThemeProvider>
  </body>
</html>
  • O que demonstra: Configuração raiz obrigatória, com suppressHydrationWarning evitando warning de hydration mismatch.
const { setTheme } = useTheme()
<DropdownMenuItem onClick={() => setTheme("light")}>Light</DropdownMenuItem>
  • O que demonstra: useTheme() de next-themes expõe setTheme direto, sem contexto customizado.

Anti-patterns

  • Esquecer suppressHydrationWarning: causa warning de React porque o class do <html> é decidido no client (localStorage/prefers-color-scheme) e diverge do SSR.

Key Takeaways

  1. npm install next-themes é o único pré-requisito de dependência.
  2. attribute="class" é o que faz a integração funcionar com as classes dark: do Tailwind.
  3. ModeToggle usa Sun/Moon com dark:scale-0/dark:scale-100 para animação cross-fade entre ícones.

Connects To

  • dark-mode: índice geral.
  • Dropdown Menu: usado para o seletor Light/Dark/System.