diff --git a/src/app.html b/src/app.html index 46b5aa6..6b86afc 100644 --- a/src/app.html +++ b/src/app.html @@ -10,9 +10,26 @@ - + + + + + + diff --git a/src/lib/stores.ts b/src/lib/stores.ts index fc76261..32acb5d 100644 --- a/src/lib/stores.ts +++ b/src/lib/stores.ts @@ -8,13 +8,28 @@ export const colorModeKey = `color-mode` type ColorMode = `light` | `dark` | `system` -export const colorMode = writable( - (has_local_store && localStorage[colorModeKey]) || `system`, -) +// Initialize to 'system' for SSR, then hydrate from localStorage on client +export const colorMode = writable(`system`) -colorMode.subscribe( - (val: ColorMode) => has_local_store && (localStorage[colorModeKey] = val), -) +// Flag to track if we've hydrated from localStorage +let colorModeHydrated = false + +export function hydrateColorMode() { + if (!colorModeHydrated && has_local_store) { + const stored = localStorage[colorModeKey] as ColorMode | undefined + if (stored) { + colorMode.set(stored) + } + colorModeHydrated = true + } +} + +// Only persist to localStorage AFTER hydration (to avoid overwriting stored value) +colorMode.subscribe((val: ColorMode) => { + if (colorModeHydrated && has_local_store) { + localStorage[colorModeKey] = val + } +}) // Custom session store implementation to replace svelte-zoo function createSessionStore(key: string, initialValue: T) { diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 11dada6..348eb8b 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -1,5 +1,6 @@ @@ -33,7 +41,6 @@ -
diff --git a/static/dark-theme.css b/static/dark-theme.css index 79e3683..abbd0a7 100644 --- a/static/dark-theme.css +++ b/static/dark-theme.css @@ -1,4 +1,5 @@ -:root { +/* Dark theme - applies when data-theme="dark" or system preference is dark */ +[data-theme='dark'] { --text-color: white; --link-color: var(--light-blue); --hover-color: var(--green); diff --git a/static/light-theme.css b/static/light-theme.css index 7fa944a..7529fd2 100644 --- a/static/light-theme.css +++ b/static/light-theme.css @@ -1,4 +1,6 @@ -:root { +/* Light theme - applies when data-theme="light" or system preference is light */ +:root, +[data-theme='light'] { --text-color: black; --link-color: var(--blue); --hover-color: var(--light-blue); diff --git a/static/system-theme.css b/static/system-theme.css index 16ef5bf..05beb93 100644 --- a/static/system-theme.css +++ b/static/system-theme.css @@ -1,3 +1,22 @@ -@import url('/light-theme.css') (prefers-color-scheme: light); +/* System theme - uses media queries to follow OS preference */ +/* Light is the default via light-theme.css :root selector */ -@import url('/dark-theme.css') (prefers-color-scheme: dark); +/* Apply dark theme when system preference is dark AND data-theme is "system" */ +@media (prefers-color-scheme: dark) { + [data-theme='system'] { + --text-color: white; + --link-color: var(--light-blue); + --hover-color: var(--green); + --body-bg: var(--darker-blue); + --accent-bg: var(--alt-gray); + --light-bg: var(--dark-gray); + --shadow: black; + --border-color: var(--dark-green); + --heading-color: var(--light-green); + --header-bg: var(--darker-blue); + --header-color: var(--light-blue); + --footer-bg: black; + --invert: 1; + --transparent: rgba(0, 0, 0, 0.5); + } +}