feat: implement theme persistence and selection in header component, enhancing user experience with localStorage integration
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
import { resolve } from '$app/paths';
|
||||
import logo from '$lib/assets/logo_governo_PE.png';
|
||||
import type { Snippet } from 'svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import { aplicarTemaDaisyUI } from '$lib/utils/temas';
|
||||
|
||||
type HeaderProps = {
|
||||
left?: Snippet;
|
||||
@@ -9,6 +11,43 @@
|
||||
};
|
||||
|
||||
const { left, right }: HeaderProps = $props();
|
||||
|
||||
let themeSelectEl: HTMLSelectElement | null = null;
|
||||
|
||||
function safeGetThemeLS(): string | null {
|
||||
try {
|
||||
const t = localStorage.getItem('theme');
|
||||
return t && t.trim() ? t : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
const persisted = safeGetThemeLS();
|
||||
if (persisted) {
|
||||
// Sincroniza UI + HTML com o valor persistido (evita select ficar "aqua" indevido)
|
||||
if (themeSelectEl && themeSelectEl.value !== persisted) {
|
||||
themeSelectEl.value = persisted;
|
||||
}
|
||||
aplicarTemaDaisyUI(persisted);
|
||||
}
|
||||
});
|
||||
|
||||
function onThemeChange(e: Event) {
|
||||
const nextValue = (e.currentTarget as HTMLSelectElement | null)?.value ?? null;
|
||||
|
||||
// Se o theme-change não atualizar (caso comum após login/logout),
|
||||
// garantimos aqui a persistência + aplicação imediata.
|
||||
if (nextValue) {
|
||||
try {
|
||||
localStorage.setItem('theme', nextValue);
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
aplicarTemaDaisyUI(nextValue);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<header
|
||||
@@ -36,9 +75,11 @@
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
<select
|
||||
bind:this={themeSelectEl}
|
||||
class="select select-sm bg-base-100 border-base-300 w-40"
|
||||
aria-label="Selecionar tema"
|
||||
data-choose-theme
|
||||
onchange={onThemeChange}
|
||||
>
|
||||
<option value="aqua">Aqua</option>
|
||||
<option value="sgse-blue">Azul</option>
|
||||
|
||||
@@ -40,9 +40,6 @@
|
||||
if (result.error) {
|
||||
console.error('Sign out error:', result.error);
|
||||
}
|
||||
// Resetar tema para padrão ao fazer logout
|
||||
const { aplicarTemaPadrao } = await import('$lib/utils/temas');
|
||||
aplicarTemaPadrao();
|
||||
goto(resolve('/home'));
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -144,6 +144,52 @@ export function obterNomeDaisyUI(id: TemaId | string | null | undefined): string
|
||||
return temaParaDaisyUI[tema.id] || 'aqua';
|
||||
}
|
||||
|
||||
/**
|
||||
* Lê o tema persistido pelo `theme-change` (chave "theme") no localStorage.
|
||||
* Retorna o nome do tema do DaisyUI (ex.: "dark", "light", "aqua", "sgse-blue").
|
||||
*/
|
||||
export function obterTemaPersistidoNoLocalStorage(chave: string = 'theme'): string | null {
|
||||
if (typeof window === 'undefined') return null;
|
||||
try {
|
||||
const tema = window.localStorage.getItem(chave);
|
||||
return tema && tema.trim() ? tema : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Aplica diretamente um tema do DaisyUI no `<html data-theme="...">`.
|
||||
* (Não altera o localStorage)
|
||||
*/
|
||||
export function aplicarTemaDaisyUI(tema: string): void {
|
||||
if (typeof document === 'undefined') return;
|
||||
const htmlElement = document.documentElement;
|
||||
if (!htmlElement) return;
|
||||
|
||||
// Normaliza qualquer estado anterior
|
||||
htmlElement.removeAttribute('data-theme');
|
||||
// Evita que `body[data-theme]` sobrescreva o tema do `<html>`
|
||||
if (document.body) document.body.removeAttribute('data-theme');
|
||||
|
||||
htmlElement.setAttribute('data-theme', tema);
|
||||
// Forçar reflow para garantir que o CSS seja aplicado
|
||||
void htmlElement.offsetHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Garante que o tema do `<html>` reflita SEMPRE o valor persistido no localStorage.
|
||||
* Se não houver tema persistido, aplica o tema padrão.
|
||||
*/
|
||||
export function aplicarTemaDoLocalStorage(): void {
|
||||
const temaPersistido = obterTemaPersistidoNoLocalStorage('theme');
|
||||
if (temaPersistido) {
|
||||
aplicarTemaDaisyUI(temaPersistido);
|
||||
return;
|
||||
}
|
||||
aplicarTemaPadrao();
|
||||
}
|
||||
|
||||
/**
|
||||
* Aplicar tema ao documento HTML
|
||||
* NÃO salva no localStorage - apenas no banco de dados do usuário
|
||||
|
||||
Reference in New Issue
Block a user