Dark Theme Implementation
Architecture
Three-Layer System:
- Server-side detection (
+layout.server.ts) - reads theme cookie, defaults to light - Client-side reactivity (Svelte 5 store with
$state) - handles theme changes - CSS implementation (
light-dark()+color-scheme) - automatic theme switching
Key Files
lib/stores/theme.svelte.ts- Svelte 5 store with toggle methodlib/components/ui/ThemeToggle.svelte- animated toggle with icons + cookie persistenceroutes/+layout.server.ts- server-side theme detection from cookiesroutes/+layout.svelte- appliesdata-themeattribute +color-schemeCSStheme.scss- CSS custom properties usinglight-dark()function
Implementation Details
Store Pattern:
class ThemeStore {
theme: Theme = $state(initTheme)
toggle() { this.theme = this.theme === 'dark' ? 'light' : 'dark' }
}
CSS Strategy:
- Uses light-dark() function for automatic theme switching
- Sets color-scheme: light/dark on <html> for native browser elements
- All colors defined as CSS custom properties with light/dark values
CSS Color Scheme:
/* Change the global color schema */
:global(html) {
color-scheme: light;
}
:global(html:has(.container[data-theme='dark'])) {
color-scheme: dark;
}
Persistence:
- Theme stored in cookie with 1-year expiration
- Server reads cookie on page load for SSR
- Client updates cookie via $effect when theme changes
Toggle Component:
- Checkbox input with animated sun/moon icons
- Grid-based overlay system for smooth transitions
- Reactive to store changes with visual feedback