1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2026-06-29 20:25:58 -04:00

move dark mode code from module back to here for now

This commit is contained in:
2021-12-01 14:43:22 -05:00
parent a3c2bbcab0
commit 6f6de426da
9 changed files with 106 additions and 70 deletions
+87 -21
View File
@@ -1,25 +1,91 @@
import { init as initDarkMode } from "dark-mode-switcheroo";
// use a specified element(s) to trigger swap when clicked
const toggle = document.querySelector(".dark-mode-toggle");
// HACK: disable theme transition until user's preference is auto-restored (1/2)
const disableTransitionCSSHack = document.createElement("style");
document.head.append(disableTransitionCSSHack);
disableTransitionCSSHack.sheet.insertRule(`
*,
::before,
::after {
transition-property: none !important;
// check for existing preference in local storage
const storageKey = "theme";
const pref = localStorage.getItem(storageKey);
// prepare a temporary stylesheet for fancy transitions
const fadeStyle = document.createElement("style");
// change CSS via these <body> classes:
const dark = "dark";
const light = "light";
// which class is <body> set to initially?
const defaultTheme = light;
// keep track of current state no matter how we got there
let active = defaultTheme === dark;
// receives a class name and switches <body> to it
const activateTheme = (theme, opts) => {
if (opts?.fade) {
document.head.append(fadeStyle);
// apply a short transition to all properties of all elements
// TODO: this causes some extreme performance hiccups (especially in chromium)
fadeStyle.sheet.insertRule(`
*, ::before, ::after {
transition: all 0.15s linear !important;
}
`);
// remove the stylesheet when body is done transitioning
document.body.addEventListener("transitionend", () => {
fadeStyle.remove();
});
}
`);
initDarkMode({
toggle: document.querySelector(".dark-mode-toggle"),
onInit: (t) => {
// make toggle visible now that we know JS is enabled
t.style.display = "block";
document.body.classList.remove(dark, light);
document.body.classList.add(theme);
active = theme === dark;
// HACK: re-enable theme transitions after a very short delay, otherwise there's a weird race condition (2/2)
setTimeout(() => {
disableTransitionCSSHack.remove();
}, 500);
},
});
if (opts?.save) {
localStorage.setItem(storageKey, theme);
}
};
// user has never clicked the button, so go by their OS preference until/if they do so
if (!pref) {
// returns media query selector syntax
// https://drafts.csswg.org/mediaqueries-5/#prefers-color-scheme
const prefers = (colorScheme) => `(prefers-color-scheme: ${colorScheme})`;
// check for OS dark/light mode preference and switch accordingly
// default to `defaultTheme` set above if unsupported
if (window.matchMedia(prefers("dark")).matches) {
activateTheme(dark);
} else if (window.matchMedia(prefers("light")).matches) {
activateTheme(light);
} else {
activateTheme(defaultTheme);
}
// real-time switching (if supported by OS/browser)
window.matchMedia(prefers("dark")).addEventListener("change", (e) => e.matches && activateTheme(dark));
window.matchMedia(prefers("light")).addEventListener("change", (e) => e.matches && activateTheme(light));
} else if (pref === dark || pref === light) {
// if user already explicitly toggled in the past, restore their preference
activateTheme(pref);
} else {
// fallback to default theme (this shouldn't happen)
activateTheme(defaultTheme);
}
// don't freak out if page happens not to have a toggle
if (toggle) {
// make toggle visible now that we know JS is enabled
toggle.style.display = "block";
// handle toggle click
toggle.addEventListener("click", () => {
// switch to the opposite theme & save preference in local storage
// TODO: enable fade.
if (active) {
activateTheme(light, { save: true });
} else {
activateTheme(dark, { save: true });
}
});
}