feat: add light/dark theme toggle with system preference detection

- Implement theme store with localStorage persistence
- Add ThemeToggle component with animated icon transitions
- Update color system with semantic tokens for light/dark modes
- Add blocking script in app.html to prevent FOUC
- Apply theme-aware styling across all public and admin pages
This commit is contained in:
2026-01-06 20:31:24 -06:00
parent 0149dc1df9
commit 5c4d3b6efa
26 changed files with 336 additions and 190 deletions
+25
View File
@@ -0,0 +1,25 @@
<script lang="ts">
import { themeStore } from "$lib/stores/theme.svelte";
import IconSun from "~icons/lucide/sun";
import IconMoon from "~icons/lucide/moon";
</script>
<button
type="button"
onclick={() => themeStore.toggle()}
aria-label={themeStore.isDark ? "Switch to light mode" : "Switch to dark mode"}
class="relative size-9 rounded-md border border-zinc-300 dark:border-zinc-700 bg-zinc-100 dark:bg-zinc-900/50 hover:bg-zinc-200 dark:hover:bg-zinc-800/70 transition-all duration-200"
>
<div class="absolute inset-0 flex items-center justify-center">
<IconSun
class="size-5 text-zinc-600 dark:text-zinc-400 transition-all duration-300 {themeStore.isDark
? 'rotate-90 scale-0 opacity-0'
: 'rotate-0 scale-100 opacity-100'}"
/>
<IconMoon
class="absolute size-5 text-zinc-600 dark:text-zinc-400 transition-all duration-300 {themeStore.isDark
? 'rotate-0 scale-100 opacity-100'
: '-rotate-90 scale-0 opacity-0'}"
/>
</div>
</button>