Initial design based off original website, some things still to do
This commit is contained in:
62
src/components/ThemeManager.astro
Normal file
62
src/components/ThemeManager.astro
Normal file
@@ -0,0 +1,62 @@
|
||||
---
|
||||
type Props = {
|
||||
defaultTheme?: "auto" | "dark" | "light" | undefined;
|
||||
};
|
||||
|
||||
const { defaultTheme = "auto" } = Astro.props;
|
||||
---
|
||||
|
||||
<script is:inline data-default-theme={defaultTheme}>
|
||||
window.theme ??= (() => {
|
||||
const defaultTheme =
|
||||
document.currentScript.getAttribute("data-default-theme");
|
||||
const storageKey = "theme";
|
||||
const store =
|
||||
typeof localStorage !== "undefined"
|
||||
? localStorage
|
||||
: { getItem: () => null, setItem: () => {} };
|
||||
|
||||
const mediaMatcher = window.matchMedia("(prefers-color-scheme: light)");
|
||||
let systemTheme = mediaMatcher.matches ? "light" : "dark";
|
||||
mediaMatcher.addEventListener("change", (event) => {
|
||||
systemTheme = event.matches ? "light" : "dark";
|
||||
applyTheme(getTheme());
|
||||
});
|
||||
|
||||
function applyTheme(theme) {
|
||||
const resolvedTheme = theme === "auto" ? systemTheme : theme;
|
||||
document.documentElement.dataset.theme = resolvedTheme;
|
||||
document.documentElement.style.colorScheme = resolvedTheme;
|
||||
document.dispatchEvent(
|
||||
new CustomEvent("theme-changed", {
|
||||
detail: { theme, systemTheme, defaultTheme }
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function setTheme(theme = defaultTheme) {
|
||||
store.setItem(storageKey, theme);
|
||||
applyTheme(theme);
|
||||
}
|
||||
|
||||
function getTheme() {
|
||||
return store.getItem(storageKey) || defaultTheme;
|
||||
}
|
||||
|
||||
function getSystemTheme() {
|
||||
return systemTheme;
|
||||
}
|
||||
|
||||
function getDefaultTheme() {
|
||||
return defaultTheme;
|
||||
}
|
||||
|
||||
return { setTheme, getTheme, getSystemTheme, getDefaultTheme };
|
||||
})();
|
||||
theme.setTheme(theme.getTheme());
|
||||
</script>
|
||||
<script>
|
||||
document.addEventListener("astro:after-swap", () =>
|
||||
window.theme.setTheme(window.theme.getTheme())
|
||||
);
|
||||
</script>
|
||||
Reference in New Issue
Block a user