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

move light/dark class from <body> to <html> and inline restoration script to (hopefully) improve the white flashes

This commit is contained in:
2021-12-15 13:49:56 -05:00
parent c2789e24d4
commit 766362a9da
14 changed files with 61 additions and 67 deletions
+21
View File
@@ -0,0 +1,21 @@
/* eslint-disable no-var */
// A super tiny script to restore dark mode off the bat (to hopefully avoid blinding flashes of white).
// NOTE: This is inlined by Hugo/esbuild (see layouts/partials/head/restore-theme.html) instead of Webpack.
import { getDarkPref } from "./src/utils/theme.js";
try {
var cl = document.documentElement.classList;
var pref = getDarkPref();
// set `<html class="dark">` if either the user has explicitly toggled in the past or if their OS is in dark mode
if (pref === "true" || (!pref && window.matchMedia("(prefers-color-scheme: dark)").matches)) {
cl.remove("light");
cl.add("dark");
}
// TODO: fix real-time switching (works but bulb icon isn't updated)
// window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (e) => e.matches && setDark(true));
// window.matchMedia("(prefers-color-scheme: light)").addEventListener("change", (e) => e.matches && setDark(false));
} catch (error) {}
+4 -2
View File
@@ -1,6 +1,6 @@
import { h } from "preact";
import { useState, useEffect } from "preact/hooks";
import { isDark, setDarkClass, setDarkPref } from "../utils/theme.js";
import { isDark, setDarkPref } from "../utils/theme.js";
// react components:
import BulbOn from "../assets/bulb-on.svg";
@@ -11,7 +11,9 @@ const ThemeToggle = () => {
const [dark, setDark] = useState(isDark());
useEffect(() => {
return setDarkClass(dark);
// sets appropriate `<html class="...">`
document.documentElement.classList.remove("dark", "light");
document.documentElement.classList.add(dark ? "dark" : "light");
}, [dark]);
const handleToggle = () => {
-20
View File
@@ -1,28 +1,8 @@
import { h, render } from "preact";
import { getDarkPref, setDarkClass } from "./utils/theme.js";
// react components:
import ThemeToggle from "./components/ThemeToggle.js";
// check for existing preference in local storage
const pref = getDarkPref();
// do initialization before *any* react-related stuff to avoid white flashes as much as possible
if (pref) {
// restore user's preference if they've explicitly toggled it in the past
setDarkClass(pref === "true");
} else {
// check for OS dark mode preference and switch accordingly
// https://drafts.csswg.org/mediaqueries-5/#prefers-color-scheme
try {
setDarkClass(window.matchMedia("(prefers-color-scheme: dark)").matches);
} catch (e) {}
// TODO: fix real-time switching (works but bulb icon isn't updated)
// window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (e) => e.matches && setDark(true));
// window.matchMedia("(prefers-color-scheme: light)").addEventListener("change", (e) => e.matches && setDark(false));
}
// finally render the nifty lightbulb in the header
if (typeof window !== "undefined" && document.querySelector(".theme-toggle")) {
render(<ThemeToggle />, document.querySelector(".theme-toggle"));
+2 -13
View File
@@ -3,17 +3,6 @@ const storageKey = "dark_mode";
export const getDarkPref = () => localStorage.getItem(storageKey);
export const setDarkPref = (pref) => localStorage.setItem(storageKey, pref);
// use the body class as a hint to what the theme was set to outside of the button component
// use the `<html class="...">` as a hint to what the theme was set to outside of the button component
// there's probably (definitely) a cleaner way to do this..?
export const isDark = () => document.body.classList?.contains("dark");
// sets appropriate `<body class="...">`
export const setDarkClass = (dark) => {
if (dark) {
document.body.classList.add("dark");
document.body.classList.remove("light");
} else {
document.body.classList.add("light");
document.body.classList.remove("dark");
}
};
export const isDark = () => document.documentElement.classList.contains("dark");