feat(fase-9): wire ThemeToggle into /settings + cross-device theme sync
Closes 9.1.6 (settings UI), 9.1.7 (reactivity), 9.1.8 (Playwright E2E). - /settings now has an "Appearance" section housing ThemeToggle. The onChange callback fires an UPDATE on public.users.theme so the choice follows the user across devices. The DB write is best-effort: a failed UPDATE does not roll back the immediate localStorage + <html data-theme> flip the toggle already performed. - Root +layout.svelte calls initTheme() once on mount so the JS-side stores hydrate from localStorage (the inline anti-FOUC script in app.html has already painted the correct theme by this point — this just rebuilds the JS state on top so reactive consumers see it). - (app)/+layout.svelte gains a one-shot effect that reads public.users.theme on first hydration and adopts the remote value when it differs from localStorage. Defers the PostgREST query through setTimeout(..., 0) per the Supabase auth-lock gotcha. - tests/e2e/theme.test.ts adds T-01 (toggle persists across reload), T-02 (system mode follows emulated prefers-color-scheme), and T-03 (refresh in dark mode never paints a light first frame, including on /logged-out which lives outside the (app) group and relies entirely on the inline app.html script). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -8,8 +8,15 @@
|
||||
import { userCollectives, currentCollective } from '$lib/stores/collective';
|
||||
import { ParaglideJS } from '@inlang/paraglide-sveltekit';
|
||||
import { i18n } from '$lib/i18n';
|
||||
import { initTheme } from '$lib/theme';
|
||||
|
||||
onMount(() => {
|
||||
// Fase 9.1: hydrate the theme stores from localStorage and start
|
||||
// listening for OS prefers-color-scheme changes. The inline script
|
||||
// in app.html has already set <html data-theme> synchronously to
|
||||
// avoid FOUC — initTheme just builds the JS-side state on top.
|
||||
initTheme();
|
||||
|
||||
// Fase 6.1: register the PWA service worker. `@vite-pwa/sveltekit` does
|
||||
// not auto-register — the virtual module is a no-op unless called.
|
||||
void import('virtual:pwa-register').then(({ registerSW }) => {
|
||||
|
||||
Reference in New Issue
Block a user