SWCore / Componentes / Day (tema)

Day (tema) Componentes

Alterna entre tema claro e escuro com persistência em localStorage, sincronização entre abas, detecção de preferência do sistema e atalho de teclado — zero configuração.

O que é

Controla qual tema (claro/escuro) a página usa, lembrando a escolha entre visitas e respeitando a preferência do sistema operacional na primeira vez. Quando nenhum botão próprio existe na página, injeta automaticamente um FAB colado na borda direita da tela, com um botão de sol e um de lua — sem opção "sistema", só as duas escolhas reais.

Como funciona

Detecta a preferência salva no localStorage; sem nada salvo, usa prefers-color-scheme do sistema. Se nenhuma página tiver um botão real com sw-day, injeta um FAB colado na borda direita, centralizado verticalmente — um par de botões empilhados (sol/lua), cada um define o tema direto ao clicar, e o botão do tema atual fica destacado na cor primária. Atalho Ctrl+Shift+D alterna a qualquer momento.

Exemplos

1. Botões de Toggle — adicione sw-day em qualquer elemento Ao vivo
<!-- Qualquer elemento com sw-day vira um toggle -->
<button sw-day class="sw-btn sw-btn-pil">
  <i class="sw-daytg-ico"></i> <!-- ícone ☀️/🌙 auto-injetado -->
  Alternar tema
</button>

<!-- Só ícone: deixe vazio — sw-day.js injeta o ícone e o aria-label sozinho -->
<button sw-day class="sw-btn sw-btn-rnd"></button>
2. Como funciona — variáveis CSS por tema Ao vivo
DARK MODE
--surface: neu-12 --text: neu-2 --border: neu-10
LIGHT MODE
--surface: neu-1 --text: neu-12 --border: neu-3
/* Variáveis semânticas gerenciadas automaticamente pelo SW.Day */
html[sw-theme="light"] {
  --surface:    var(--sw-neu-1);
  --text:       var(--sw-neu-12);
  --border:     var(--sw-neu-4);
}
3. Sincronização de Imagem e Fundo — troca de verdade ao alternar o tema Ao vivo

Logo trocando de arquivo

A logo real da barra lateral desta doc — clique no botão de tema (rodapé da barra lateral ou topo, no mobile) e veja o arquivo mudar de verdade.

Fundo trocando de cor

O fundo deste cartão está preso ao tema — não é imagem, é a propriedade CSS background sendo trocada em tempo real pelo módulo.

<!-- Troca o src da imagem conforme o tema -->
<img src="logo-dark.png"
     sw-day-img-light="logo-light.png"
     sw-day-img-dark="logo-dark.png">

<!-- Troca a cor (ou "url(...)" para uma imagem) de fundo do elemento -->
<div sw-day-bg-light="#fef3c7"
     sw-day-bg-dark="#0d131d">
</div>
4. Sincronização de Fonte Ao vivo

Esta fonte muda conforme o tema!

No tema claro: Sans-Serif. No tema escuro: Mono (JetBrains). Alterne o tema com o botão na lateral →

<!-- Troca a família de fonte ao mudar de tema -->
<h1 sw-day-font-light="var(--sw-f-san)"
    sw-day-font-dark="var(--sw-f-mon)">
  Título Dinâmico
</h1>
5. Persistência + Sincronização entre Abas Ao vivo

Fluxo de decisão

1 localStorage tem sw-theme salvo?
2 Se não → prefers-color-scheme do sistema
3 Se não → padrão dark

Recursos automáticos

Persiste entre sessões (localStorage)
Sincroniza entre abas abertas
Respeita prefers-color-scheme
Atalho Ctrl+Shift+D
Evento sw:theme:change
Ícone ☀️/🌙 auto-injetado
<div style="display:grid;grid-template-columns:1fr 1fr;gap:1.5rem;">

  <div>
    <p style="font-size:.8rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted);margin-bottom:.75rem;">Fluxo de decisão</p>
    <div style="background:var(--surface);border:1px solid var(--border);border-radius:0.5rem;padding:1.25rem;display:flex;flex-direction:column;gap:.75rem;">
      <div style="display:flex;align-items:center;gap:.75rem;font-size:.9rem;">
        <span style="width:2rem;height:2rem;border-radius:50%;background:var(--color-primary);color:#fff;display:inline-flex;align-items:center;justify-content:center;font-size:.8rem;font-weight:700;flex-shrink:0;">1</span>
        <span><code>localStorage</code> tem <code>sw-theme</code> salvo?</span>
      </div>
      <div style="display:flex;align-items:center;gap:.75rem;font-size:.9rem;">
        <span style="width:2rem;height:2rem;border-radius:50%;background:var(--surface-active);color:var(--text-muted);display:inline-flex;align-items:center;justify-content:center;font-size:.8rem;font-weight:700;flex-shrink:0;">2</span>
        <span>Se não → <code>prefers-color-scheme</code> do sistema</span>
      </div>
      <div style="display:flex;align-items:center;gap:.75rem;font-size:.9rem;">
        <span style="width:2rem;height:2rem;border-radius:50%;background:var(--surface-active);color:var(--text-muted);display:inline-flex;align-items:center;justify-content:center;font-size:.8rem;font-weight:700;flex-shrink:0;">3</span>
        <span>Se não → padrão <code>dark</code></span>
      </div>
    </div>
  </div>

  <div>
    <p style="font-size:.8rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted);margin-bottom:.75rem;">Recursos automáticos</p>
    <div style="background:var(--surface);border:1px solid var(--border);border-radius:0.5rem;padding:1.25rem;display:flex;flex-direction:column;gap:.6rem;font-size:.88rem;">
      <div style="display:flex;align-items:center;gap:.5rem;"><i class="swi-check" style="color:#22c55e;"></i> Persiste entre sessões (localStorage)</div>
      <div style="display:flex;align-items:center;gap:.5rem;"><i class="swi-check" style="color:#22c55e;"></i> Sincroniza entre abas abertas</div>
      <div style="display:flex;align-items:center;gap:.5rem;"><i class="swi-check" style="color:#22c55e;"></i> Respeita prefers-color-scheme</div>
      <div style="display:flex;align-items:center;gap:.5rem;"><i class="swi-check" style="color:#22c55e;"></i> Atalho Ctrl+Shift+D</div>
      <div style="display:flex;align-items:center;gap:.5rem;"><i class="swi-check" style="color:#22c55e;"></i> Evento sw:theme:change</div>
      <div style="display:flex;align-items:center;gap:.5rem;"><i class="swi-check" style="color:#22c55e;"></i> Ícone ☀️/🌙 auto-injetado</div>
    </div>
  </div>

</div>
6. API JavaScript Ao vivo

Controle programático completo via SW.Day:

// Setar tema
SW.Day.set('dark');
SW.Day.set('light');

// Toggle (dark → light → dark)
SW.Day.toggle();

// Ler tema atual
console.log(SW.Day.theme); // 'dark' | 'light'

// Escutar mudança de tema
document.documentElement.addEventListener('sw:theme:change', (e) => {
  console.log('Tema:', e.detail.theme);
  // atualizar gráficos, ícones, etc.
});

// Exemplo real: sincronizar Chart.js com o tema
document.documentElement.addEventListener('sw:theme:change', ({ detail }) => {
  const isDark = detail.theme === 'dark';
  myChart.options.scales.x.grid.color = isDark ? '#333' : '#ddd';
  myChart.update();
});

Atributos

sw-day
no botão — alterna o tema ao clicar
sw-day-demo
marca um sw-day como exemplo — não impede o FAB padrão de aparecer
sw-day-lock="dark|light" (no <html>)
trava o site num único tema, desativa toggle, atalho, storage e esconde qualquer botão de troca
sw-day-no-fab (no <html>)
desativa o FAB padrão nesta página (mesmo sem nenhum botão próprio)
sw-day-img-{tema}
troca o src da imagem ao mudar de tema
sw-day-bg-{tema}
troca o background-image ou cor ao mudar de tema
sw-day-font-{tema}
troca a família de fonte ao mudar de tema

Variantes

Nenhum.

Eventos

sw:theme:change
{ theme } — disparado no <html> ao trocar de tema

API (JavaScript)

SW.Day.toggle()
alterna entre claro/escuro
SW.Day.set(tema, persistir?)
define um tema específico: "dark" ou "light"
SW.Day.theme
getter — tema atual ("dark" ou "light")

Requisitos

  • Depende de localStorage pra lembrar a escolha entre visitas (sem ele, ainda funciona, só não persiste).
  • Para evitar flash de tema ao carregar, inclua o anti-flash inline no <head> antes de qualquer CSS: <script>try{var t=localStorage.getItem('sw-theme');if(t)document.documentElement.setAttribute('sw-theme',t)}catch(e){}</script>

Limitações — o que ele não faz

Nenhuma.