🐛 fix(clock): use 'lume' as default theme variant instead of 'amber'

'amber' doesn't exist in THEME_VARIANTS - available themes are:
lume, nature, stone, ocean

Also added proper SSR fallbacks for theme store

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Till-JS 2025-12-03 15:58:34 +01:00
parent 180eced0d0
commit 79dd56403e
2 changed files with 40 additions and 24 deletions

View file

@ -1,6 +1,7 @@
/**
* Theme store for Clock app
* Manages light/dark mode and theme variants
* SSR-safe implementation
*/
import { browser } from '$app/environment';
@ -15,10 +16,15 @@ import {
const MODE_KEY = 'clock-theme-mode';
const VARIANT_KEY = 'clock-theme-variant';
// State
let mode = $state<ThemeMode>('system');
let variant = $state<ThemeVariant>('amber');
// Default values for SSR
const DEFAULT_MODE: ThemeMode = 'system';
const DEFAULT_VARIANT: ThemeVariant = 'lume';
// State (only used client-side, but initialized for SSR)
let mode = $state<ThemeMode>(DEFAULT_MODE);
let variant = $state<ThemeVariant>(DEFAULT_VARIANT);
let isDark = $state(false);
let initialized = $state(false);
// Get system preference
function getSystemPrefersDark(): boolean {
@ -31,43 +37,49 @@ function applyTheme() {
if (!browser) return;
// Determine if dark mode
const shouldBeDark = mode === 'system' ? getSystemPrefersDark() : mode === 'dark';
const currentMode = mode ?? DEFAULT_MODE;
const shouldBeDark = currentMode === 'system' ? getSystemPrefersDark() : currentMode === 'dark';
isDark = shouldBeDark;
// Apply to document
const currentVariant = variant ?? DEFAULT_VARIANT;
document.documentElement.classList.toggle('dark', shouldBeDark);
document.documentElement.setAttribute('data-theme', variant);
document.documentElement.setAttribute('data-theme', currentVariant);
}
// Listen for system preference changes
// Listen for system preference changes (only in browser)
if (browser) {
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
if (mode === 'system') {
if ((mode ?? DEFAULT_MODE) === 'system') {
applyTheme();
}
});
}
export const theme = {
// Getters
get mode() {
return mode;
// Getters (SSR-safe with fallbacks)
get mode(): ThemeMode {
return mode ?? DEFAULT_MODE;
},
get variant() {
return variant;
get variant(): ThemeVariant {
return variant ?? DEFAULT_VARIANT;
},
get isDark() {
return isDark;
get isDark(): boolean {
return isDark ?? false;
},
get variants() {
get variants(): readonly ThemeVariant[] {
return THEME_VARIANTS;
},
get initialized(): boolean {
return initialized;
},
/**
* Initialize theme from localStorage
* Initialize theme from localStorage (client-side only)
*/
initialize() {
if (!browser) return;
if (initialized) return;
// Load saved preferences
const savedMode = localStorage.getItem(MODE_KEY) as ThemeMode | null;
@ -81,6 +93,7 @@ export const theme = {
variant = savedVariant;
}
initialized = true;
applyTheme();
},
@ -99,7 +112,8 @@ export const theme = {
* Toggle between light and dark
*/
toggleMode() {
const newMode = isDark ? 'light' : 'dark';
const currentDark = isDark ?? false;
const newMode = currentDark ? 'light' : 'dark';
this.setMode(newMode);
},

View file

@ -30,14 +30,14 @@
// Use theme store's isDark directly
let isDark = $derived(theme.isDark);
// Theme variant dropdown items
// Theme variant dropdown items (with SSR fallback)
let themeVariantItems = $derived<PillDropdownItem[]>([
...theme.variants.map((variant) => ({
...(theme.variants || []).map((variant) => ({
id: variant,
label: THEME_DEFINITIONS[variant].label,
icon: THEME_DEFINITIONS[variant].icon,
label: THEME_DEFINITIONS[variant]?.label || variant,
icon: THEME_DEFINITIONS[variant]?.icon || '🎨',
onClick: () => theme.setVariant(variant),
active: theme.variant === variant,
active: (theme.variant || 'lume') === variant,
})),
{
id: 'all-themes',
@ -48,8 +48,10 @@
},
]);
// Current theme variant label
let currentThemeVariantLabel = $derived(THEME_DEFINITIONS[theme.variant].label);
// Current theme variant label (with SSR fallback)
let currentThemeVariantLabel = $derived(
THEME_DEFINITIONS[theme.variant]?.label || THEME_DEFINITIONS.lume?.label || 'Lume'
);
// Language selector items
let currentLocale = $derived($locale || 'de');