Primeiramente, por que precisamos implementar tema dark e light nos nossos projetos?
Ter esse recurso não é um requisito que fará seu projeto ter ou não mais acesso, porém ajuda muito na experiência de uso, pois existem pessoas com diferentes preferências. Entendido esse ponto, vamos ao que interessa! 😄
Entendendo o recurso no Tailwind
Para configurarmos esse recurso no Tailwind, precisamos apenas adicionar ou remover a classe dark
no elemento do HTML e usar o prefixo
dark:
nas classes dos elementos que desejamos ter estilos diferentes para cada tema.
Por exemplo:
Nesse cenário, o fundo será
bg-gray-800
como padrão (modo claro) e bg-gray-500
quando o tema escuro estiver ativo.
Como funciona no Next.js
No Next.js é um pouco diferente, pois é necessário o apoio de uma biblioteca chamada
next-themes
.
Importante: você não é obrigado a usá-la — é totalmente possível implementar o mesmo recurso manualmente — porém, ela facilita bastante o desenvolvimento.
Vamos ver exemplos usando e não usando a biblioteca.
Exemplo sem usar a biblioteca
Aqui, você será responsável por:
- Gerenciar o valor do tema no
localStorage
; - Detectar qual tema o sistema do usuário está utilizando para proporcionar uma melhor experiência.
// hooks/useTheme.ts
import { useEffect, useState } from 'react';
type Theme = 'light' | 'dark';
export function useTheme() {
const [theme, setTheme] = useState('light');
// Detecta preferências do sistema
useEffect(() => {
const savedTheme = localStorage.getItem('theme') as Theme | null;
if (savedTheme) {
setTheme(savedTheme);
} else {
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
setTheme(prefersDark ? 'dark' : 'light');
}
}, []);
// Atualiza a classe no e salva no localStorage
useEffect(() => {
const root = document.documentElement;
if (theme === 'dark') {
root.classList.add('dark');
root.classList.remove('light');
} else {
root.classList.add('light');
root.classList.remove('dark');
}
localStorage.setItem('theme', theme);
}, [theme]);
return { theme, setTheme };
}
Exemplo usando a biblioteca next-themes
next-themes
// provider/theme-provider.ts
'use client'
import { ThemeProvider as NextThemesProvider } from 'next-themes'
import * as React from 'react'
function ThemeProvider({ children, ...props }: React.ComponentProps) {
const [mounted, setMounted] = React.useState(false)
React.useEffect(() => {
setMounted(true)
}, [])
if (!mounted) {
return <>{children}>
}
return {children}
}
export { ThemeProvider }
Usando no layout raiz da aplicação:
async function RootLayout({ children }: { children: ReactNode }) {
return (
{children}
)
}
Ao usar a lib
next-themes
, ela já traz muitos recursos prontos, como:
-
defaultTheme="system"
, que automaticamente respeita a preferência do sistema do usuário; - Controle do tema via classes (
class
) no HTML; - Entre outras configurações que você pode conferir na documentação oficial: 👉 next-themes no npm
Conclusão
Ter tema dark e light no seu sistema não é um ponto crucial, mas é muito importante para melhorar a usabilidade e a interação do usuário com o seu projeto.