Implementar modo escuro com Claude Code
Modo escuro com variáveis CSS, preferência do sistema, localStorage, hidratação segura e acessibilidade.
Comece pelo risco de produto
Implementar modo escuro com Claude Code não é pedir ao Claude Code uma tela mais bonita. O objetivo é melhorar uma interface real sem quebrar conversão, leitura, acessibilidade ou layout móvel. Em produção, estados vazios, carregamento, erros, foco de teclado, textos longos, anúncios, blocos de código e CTA importam muito.
Leia também claude code design system, claude code accessibility, claude code code review. As referências oficiais são Claude Code docs, MDN prefers-color-scheme, MDN color-scheme, WCAG contrast. O pedido ao Claude Code deve conter objetivo, limites, use case, pitfall e verificação.
Prompt recomendado
Implemente esta melhoria com a menor mudança segura.
Respeite componentes, tokens de design e rotas existentes.
Cubra use case, pitfall, acessibilidade, mobile e estados de erro.
Retorne código copiável e uma review checklist.
Use case checklist
- Landing pages e artigos onde o leitor precisa ver o próximo passo.
- Dashboards SaaS com carregamento, vazio, erro e sucesso.
- Compra, cadastro e consulta onde o botão principal precisa continuar claro.
- Revisão em equipe, com código e critérios gerados por Claude Code.
Código de implementação
:root {
color-scheme: light;
--color-page: #ffffff;
--color-surface: #f8fafc;
--color-text: #0f172a;
--color-muted: #475569;
--color-border: #dbe3ef;
--color-link: #2563eb;
--color-focus: #f59e0b;
}
[data-theme="dark"] {
color-scheme: dark;
--color-page: #0b1120;
--color-surface: #111827;
--color-text: #f8fafc;
--color-muted: #cbd5e1;
--color-border: #334155;
--color-link: #93c5fd;
--color-focus: #fbbf24;
}
body {
background: var(--color-page);
color: var(--color-text);
}
:focus-visible {
outline: 3px solid var(--color-focus);
outline-offset: 3px;
}
const storageKey = "theme";
const root = document.documentElement;
const stored = localStorage.getItem(storageKey);
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
const theme = stored === "light" || stored === "dark" ? stored : prefersDark ? "dark" : "light";
root.dataset.theme = theme;
type Theme = "light" | "dark" | "system";
export function ThemeToggle({ value, onChange }: { value: Theme; onChange: (theme: Theme) => void }) {
return (
<fieldset aria-label="Theme">
{(["light", "dark", "system"] as const).map((theme) => (
<button
key={theme}
type="button"
aria-pressed={value === theme}
onClick={() => onChange(theme)}
>
{theme}
</button>
))}
</fieldset>
);
}
Evite o flash de tema (o instante de cor errada)
A primeira armadilha do modo escuro é o “flash”: por um instante a tela aparece clara e só depois fica escura ao abrir a página. Em inglês isso é chamado de FOUC (Flash of Unstyled Content). A causa é trocar o tema com JavaScript só depois que o HTML já apareceu. Se você espera o carregamento do CSS ou do React para então aplicar data-theme, durante essa espera o leitor vê a cor inicial, quase sempre clara.
A solução é executar um script muito curto, de forma síncrona e antes do corpo (dentro do <head>), olhando apenas a preferência salva e a do dispositivo para fixar data-theme antes da tela ser pintada.
<script>
(function () {
var stored = localStorage.getItem("theme");
var prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
var theme = stored === "light" || stored === "dark" ? stored : prefersDark ? "dark" : "light";
document.documentElement.dataset.theme = theme;
})();
</script>
O ponto é manter esse script leve e rodá-lo antes da renderização do corpo. Se você colocar processamento pesado ou a inicialização do React aqui, o flash volta. Em Astro ou Next.js, trate esse pequeno script à parte para fixar o tema sem esperar a hidratação do framework. Como o servidor não conhece a preferência do dispositivo, no primeiro acesso respeite a configuração do aparelho e, quando o usuário trocar, salve em localStorage para priorizar a partir da próxima visita.
Contraste, imagens e sombras legíveis no escuro
Só inverter as cores não conclui o modo escuro. Um contraste que bastava na tela clara pode ficar insuficiente sobre fundo escuro. Confira a razão de contraste entre texto e fundo mirando o mínimo de 4,5:1 indicado pela WCAG. Textos auxiliares em cinza claro, placeholders e botões desabilitados são justamente os que tendem a sumir no fundo escuro.
Imagens e sombras também precisam de ajuste. Logos e ícones feitos para fundo branco perdem a borda no escuro; para PNG transparente, coloque uma cor de fundo ou prepare uma versão para o tema escuro. Sombras que delimitavam bordas quase não aparecem no escuro, então redesenhe esses limites com uma borda como --color-border.
| Elemento | Premissa no claro | Ajuste no escuro |
|---|---|---|
| Texto auxiliar | Cinza claro basta | Aumentar a luminosidade para garantir contraste |
| Logo e ícones | Pensados para fundo branco | Aplicar fundo ou trocar pela versão escura |
| Sombra | Cinza forte delimita | Redesenhar o limite com borda |
| Cores de estado | Verde e vermelho vivos | Reduzir a saturação e adicionar um ícone |
Por fim, reveja gráficos, figuras e cores de status (sucesso em verde, alerta em vermelho). Cores muito saturadas brilham e cansam no fundo escuro; prepare tons mais suaves para o tema escuro e não comunique o estado só pela cor: acrescente ícone ou rótulo para alcançar também quem tem baixa visão ou percepção de cor diferente.
Pitfall checklist
- Otimizar só para screenshot pode piorar o fluxo real.
- Depender apenas de cor ou movimento prejudica acessibilidade.
- Não testar em 375px pode criar rolagem horizontal.
- Ignorar dados vazios, rótulos longos e rede lenta gera bugs.
- Mudanças sem relação aumentam o custo de revisão.
Verificação
Peça uma segunda passada apenas de review. Claude Code deve listar arquivos alterados, riscos, checagens de navegador e testes manuais. Depois revise no mobile, confirme ausência de overflow, rolagem do bloco de código, CTA visível e foco claro.
Monetização
Esse trabalho afeta anúncios, cards de produto, links de consulta, preços e formulários. Para aplicar em um repositório real, a página de treinamento e consultoria Claude Code transforma isso em processo repetível.
Notas extras de revisão
- Compare screenshots antes e depois, olhando CTA, anúncios, texto, formulários e blocos de código.
- Pergunte ao Claude Code o que pode ser removido, quais nomes não combinam e quais suposições são arriscadas.
- Antes do deploy, teste mobile, desktop, teclado, rede lenta, dados vazios e reload.
Nota de teste prático
Testei em três etapas: implementação, review e verificação mobile. O diff ficou menor e os problemas de layout e acessibilidade apareceram antes do deploy. Verifiquei mantendo a UI do blog intacta, observando 375px no celular, exibição normal, rede lenta e teclado, e foi o script de tema no <head> que eliminou o flash inicial sem esperar a hidratação.
PDF grátis: cheatsheet do Claude Code
Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.
Cuidamos dos seus dados e não enviamos spam.
Sobre o autor
Masa
Engenheiro focado em workflows práticos com Claude Code.
Artigos relacionados
Como pedir ao Claude Code para mexer em um único arquivo
Do desastre em que um 'deixa melhor' alterou 40 linhas nasceu um template de prompt que limita o escopo, valida e permite reverter.
Recuperar de negações de permissão no Claude Code sem enfraquecer guardrails
Transforme um comando negado em plano seguro com motivo, alternativa, provas e critérios de nova tentativa.
Claude Code Harness Smoke Test: prova de 15 minutos antes de confiar em um agente
Um smoke test para escopo, áreas bloqueadas, comandos de prova, URL pública e CTAs de receita no Claude Code.