mirror of
https://github.com/jakejarvis/jarv.is.git
synced 2026-06-29 19:05:58 -04:00
move dark mode code from module back to here for now
This commit is contained in:
+87
-21
@@ -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 });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -34,7 +34,3 @@ $font-stack-mono-variable: list.join($webfont-mono-variable, $system-fonts-mono)
|
||||
// Fancy link underline settings:
|
||||
$link-underline-opacity: 40%;
|
||||
$link-underline-size: 2px;
|
||||
|
||||
// Default fading style when switching between light/dark themes:
|
||||
$theme-transition-duration: 0.15s;
|
||||
$theme-transition-function: linear;
|
||||
|
||||
@@ -5,18 +5,7 @@
|
||||
|
||||
// Takes a map of CSS properties and theme keys (see below) and set both body.light and body.dark selectors.
|
||||
// ex. @include themes.themed((color: "text", background-color: "background-inner"));
|
||||
// Also accepts additional transitions (in shorthand) to tack on.
|
||||
@mixin themed($properties, $moreTransitions: ()) {
|
||||
// generate CSS transition shorthand for each themed property w/ default duration and function
|
||||
$defaults: ();
|
||||
@each $property, $color in $properties {
|
||||
$shorthand: $property settings.$theme-transition-duration settings.$theme-transition-function;
|
||||
$defaults: list.append($defaults, $shorthand);
|
||||
}
|
||||
|
||||
// list all transitions separated by commas (with additional shorthand(s) passed in)
|
||||
transition: list.join($moreTransitions, $defaults, $separator: comma);
|
||||
|
||||
@mixin themed($properties) {
|
||||
// keep track of the original selector(s) calling this mixin for below
|
||||
$selectors: #{&};
|
||||
|
||||
|
||||
@@ -99,13 +99,11 @@ main {
|
||||
background-repeat: no-repeat;
|
||||
background-size: 0% settings.$link-underline-size;
|
||||
padding-bottom: settings.$link-underline-size;
|
||||
transition: background-size 0.25s ease-in-out;
|
||||
|
||||
@include themes.themed(
|
||||
$properties: (
|
||||
(
|
||||
color: "links",
|
||||
),
|
||||
$moreTransitions: (
|
||||
background-size 0.25s ease-in-out,
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
@@ -133,9 +133,6 @@ body.light {
|
||||
:not(pre) > code {
|
||||
background-color: #fbfbfb;
|
||||
border-color: #d5d5d5;
|
||||
|
||||
// TODO: apply this consistently via themed() mixin like everywhere else
|
||||
transition: color 0.15s linear, background-color 0.15s linear, border-color 0.15s linear;
|
||||
}
|
||||
|
||||
div.highlight,
|
||||
@@ -224,9 +221,6 @@ body.dark {
|
||||
:not(pre) > code {
|
||||
background-color: #252525;
|
||||
border-color: #535353;
|
||||
|
||||
// TODO: apply this consistently via themed() mixin like everywhere else
|
||||
transition: color 0.15s linear, background-color 0.15s linear, border-color 0.15s linear;
|
||||
}
|
||||
|
||||
div.highlight,
|
||||
|
||||
Reference in New Issue
Block a user