diff options
| author | Dawid Rycerz <dawid@rycerz.xyz> | 2025-07-03 10:56:21 +0300 |
|---|---|---|
| committer | Dawid Rycerz <dawid@rycerz.xyz> | 2025-07-03 10:56:21 +0300 |
| commit | 456cf011b36de91c9936994b1fa45703adcd309b (patch) | |
| tree | 8e60daf998f731ac50d100fa490eaecae1168042 /src/components/ThemeProvider.astro | |
Initial fork of chrismwilliams/astro-theme-cactus theme
Diffstat (limited to 'src/components/ThemeProvider.astro')
| -rw-r--r-- | src/components/ThemeProvider.astro | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/src/components/ThemeProvider.astro b/src/components/ThemeProvider.astro new file mode 100644 index 0000000..5f0723d --- /dev/null +++ b/src/components/ThemeProvider.astro @@ -0,0 +1,44 @@ +{/* Inlined to avoid FOUC. This is a parser blocking script. */} +<script is:inline> + const lightModePref = window.matchMedia("(prefers-color-scheme: light)"); + + function getUserPref() { + const storedTheme = typeof localStorage !== "undefined" && localStorage.getItem("theme"); + return storedTheme || (lightModePref.matches ? "light" : "dark"); + } + + function setTheme(newTheme) { + if (newTheme !== "light" && newTheme !== "dark") { + return console.warn( + `Invalid theme value '${newTheme}' received. Expected 'light' or 'dark'.`, + ); + } + + const root = document.documentElement; + + // root already set to newTheme, exit early + if (newTheme === root.getAttribute("data-theme")) { + return; + } + + root.setAttribute("data-theme", newTheme); + + if (typeof localStorage !== "undefined") { + localStorage.setItem("theme", newTheme); + } + } + + // initial setup + setTheme(getUserPref()); + + // View Transitions hook to restore theme + document.addEventListener("astro:after-swap", () => setTheme(getUserPref())); + + // listen for theme-change custom event, fired in src/components/ThemeToggle.astro + document.addEventListener("theme-change", (e) => { + setTheme(e.detail.theme); + }); + + // listen for prefers-color-scheme change. + lightModePref.addEventListener("change", (e) => setTheme(e.matches ? "light" : "dark")); +</script> |
