feat(fase-9): ThemeToggle component + anti-FOUC bootstrap
Wires the dark-mode plumbing: - New $lib/theme module: themePreference + resolvedTheme stores plus initTheme() / setThemePreference(). Owns localStorage persistence, <html data-theme=...> mirroring, and the matchMedia listener that re-resolves "system" when the OS preference flips. Storage-agnostic (no Supabase coupling) so the caller persists to public.users.theme separately. - Inline anti-FOUC script in app.html reads localStorage + matchMedia synchronously and writes data-theme before the first paint — refresh in dark mode no longer flashes white. - Tailwind switched to darkMode: ['selector', '[data-theme="dark"]'] so all existing `dark:` utilities resolve from the same attribute. - :root and :root[data-theme=light] share the light token set; dark tokens move into :root[data-theme=dark]. Tokens stay as RGB triplets (rgb(var(--token) / <alpha>)) per the repo gotcha — no hsl(). - ThemeToggle.svelte: three-way radiogroup (Light / Dark / System) with paraglide messages in EN + ES. Tests (TDD): 8 new unit specs in src/lib/theme.test.ts cover defaults, localStorage round-trip, data-theme reflection, system resolution against matchMedia, invalid-value fallback, and OS preference change propagation. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -183,5 +183,9 @@
|
||||
"list_bulk_mark_checked": "Marcar",
|
||||
"list_undo_bulk_delete": "{n} eliminados",
|
||||
"list_move_title": "Mover a lista",
|
||||
"list_move_create_new": "Crear lista nueva"
|
||||
"list_move_create_new": "Crear lista nueva",
|
||||
"settings_appearance": "Apariencia",
|
||||
"settings_theme_light": "Claro",
|
||||
"settings_theme_dark": "Oscuro",
|
||||
"settings_theme_system": "Sistema"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user