mirror of
https://github.com/jakejarvis/jarv.is.git
synced 2025-04-27 12:36:20 -04:00
move dark mode code from module back to here for now
This commit is contained in:
parent
a3c2bbcab0
commit
6f6de426da
@ -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)
|
// check for existing preference in local storage
|
||||||
const disableTransitionCSSHack = document.createElement("style");
|
const storageKey = "theme";
|
||||||
document.head.append(disableTransitionCSSHack);
|
const pref = localStorage.getItem(storageKey);
|
||||||
disableTransitionCSSHack.sheet.insertRule(`
|
|
||||||
*,
|
// prepare a temporary stylesheet for fancy transitions
|
||||||
::before,
|
const fadeStyle = document.createElement("style");
|
||||||
::after {
|
|
||||||
transition-property: none !important;
|
// 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({
|
document.body.classList.remove(dark, light);
|
||||||
toggle: document.querySelector(".dark-mode-toggle"),
|
document.body.classList.add(theme);
|
||||||
onInit: (t) => {
|
active = theme === dark;
|
||||||
// make toggle visible now that we know JS is enabled
|
|
||||||
t.style.display = "block";
|
|
||||||
|
|
||||||
// HACK: re-enable theme transitions after a very short delay, otherwise there's a weird race condition (2/2)
|
if (opts?.save) {
|
||||||
setTimeout(() => {
|
localStorage.setItem(storageKey, theme);
|
||||||
disableTransitionCSSHack.remove();
|
}
|
||||||
}, 500);
|
};
|
||||||
},
|
|
||||||
});
|
// 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:
|
// Fancy link underline settings:
|
||||||
$link-underline-opacity: 40%;
|
$link-underline-opacity: 40%;
|
||||||
$link-underline-size: 2px;
|
$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.
|
// 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"));
|
// ex. @include themes.themed((color: "text", background-color: "background-inner"));
|
||||||
// Also accepts additional transitions (in shorthand) to tack on.
|
@mixin themed($properties) {
|
||||||
@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);
|
|
||||||
|
|
||||||
// keep track of the original selector(s) calling this mixin for below
|
// keep track of the original selector(s) calling this mixin for below
|
||||||
$selectors: #{&};
|
$selectors: #{&};
|
||||||
|
|
||||||
|
@ -99,13 +99,11 @@ main {
|
|||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: 0% settings.$link-underline-size;
|
background-size: 0% settings.$link-underline-size;
|
||||||
padding-bottom: settings.$link-underline-size;
|
padding-bottom: settings.$link-underline-size;
|
||||||
|
transition: background-size 0.25s ease-in-out;
|
||||||
|
|
||||||
@include themes.themed(
|
@include themes.themed(
|
||||||
$properties: (
|
(
|
||||||
color: "links",
|
color: "links",
|
||||||
),
|
|
||||||
$moreTransitions: (
|
|
||||||
background-size 0.25s ease-in-out,
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -133,9 +133,6 @@ body.light {
|
|||||||
:not(pre) > code {
|
:not(pre) > code {
|
||||||
background-color: #fbfbfb;
|
background-color: #fbfbfb;
|
||||||
border-color: #d5d5d5;
|
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,
|
div.highlight,
|
||||||
@ -224,9 +221,6 @@ body.dark {
|
|||||||
:not(pre) > code {
|
:not(pre) > code {
|
||||||
background-color: #252525;
|
background-color: #252525;
|
||||||
border-color: #535353;
|
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,
|
div.highlight,
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
"url": "https://github.com/jakejarvis/jarv.is.git"
|
"url": "https://github.com/jakejarvis/jarv.is.git"
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./assets/js/index.js",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "gulp",
|
"build": "gulp",
|
||||||
"clean": "gulp clean",
|
"clean": "gulp clean",
|
||||||
@ -32,7 +31,6 @@
|
|||||||
"@primer/octicons-react": "^16.1.1",
|
"@primer/octicons-react": "^16.1.1",
|
||||||
"@sentry/node": "^6.15.0",
|
"@sentry/node": "^6.15.0",
|
||||||
"clipboard-copy": "^4.0.1",
|
"clipboard-copy": "^4.0.1",
|
||||||
"dark-mode-switcheroo": "^0.10.0",
|
|
||||||
"dayjs": "^1.10.7",
|
"dayjs": "^1.10.7",
|
||||||
"faunadb": "^4.4.1",
|
"faunadb": "^4.4.1",
|
||||||
"get-canonical-url": "^1.1.0",
|
"get-canonical-url": "^1.1.0",
|
||||||
|
@ -21,7 +21,7 @@ export default (env, argv) => {
|
|||||||
const globalBannerText = `Licensed under MIT. Copyright (c) 2015-${new Date().getFullYear()} Jake Jarvis <https://jarv.is/>.`;
|
const globalBannerText = `Licensed under MIT. Copyright (c) 2015-${new Date().getFullYear()} Jake Jarvis <https://jarv.is/>.`;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
entry: [path.resolve(__dirname, "assets/js/index.js"), path.resolve(__dirname, "assets/sass/main.scss")],
|
entry: [path.resolve(__dirname, "assets/js/main.js"), path.resolve(__dirname, "assets/sass/main.scss")],
|
||||||
mode: isProd ? "production" : "development",
|
mode: isProd ? "production" : "development",
|
||||||
devtool: isProd ? "source-map" : "inline-source-map",
|
devtool: isProd ? "source-map" : "inline-source-map",
|
||||||
output: {
|
output: {
|
||||||
|
35
yarn.lock
35
yarn.lock
@ -945,9 +945,9 @@
|
|||||||
to-fast-properties "^2.0.0"
|
to-fast-properties "^2.0.0"
|
||||||
|
|
||||||
"@discoveryjs/json-ext@^0.5.0":
|
"@discoveryjs/json-ext@^0.5.0":
|
||||||
version "0.5.5"
|
version "0.5.6"
|
||||||
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.5.tgz#9283c9ce5b289a3c4f61c12757469e59377f81f3"
|
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz#d5e0706cf8c6acd8c6032f8d54070af261bbbb2f"
|
||||||
integrity sha512-6nFkfkmSeV/rqSaS4oWHgmpnYw194f6hmWF5is6b0J1naJZoiD0NTc9AiUwPHvWsowkjuHErCZT1wa0jg+BLIA==
|
integrity sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA==
|
||||||
|
|
||||||
"@eslint/eslintrc@^1.0.4":
|
"@eslint/eslintrc@^1.0.4":
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
@ -3003,11 +3003,6 @@ d@1, d@^1.0.1:
|
|||||||
es5-ext "^0.10.50"
|
es5-ext "^0.10.50"
|
||||||
type "^1.0.1"
|
type "^1.0.1"
|
||||||
|
|
||||||
dark-mode-switcheroo@^0.10.0:
|
|
||||||
version "0.10.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/dark-mode-switcheroo/-/dark-mode-switcheroo-0.10.0.tgz#2b38085082fa7bf4f8047e9d082afe86a38281f6"
|
|
||||||
integrity sha512-/EIoyXUE/wmyBF8vRJMOaszCIqgjb2IrnFRREQvSMkYI6QHb3A9kVgs7w+laZAvj4If64bNXpAU6C09NJnGS7g==
|
|
||||||
|
|
||||||
data-uri-to-buffer@^4.0.0:
|
data-uri-to-buffer@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz#b5db46aea50f6176428ac05b73be39a57701a64b"
|
resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz#b5db46aea50f6176428ac05b73be39a57701a64b"
|
||||||
@ -3320,9 +3315,9 @@ domelementtype@^2.0.1, domelementtype@^2.2.0:
|
|||||||
integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==
|
integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==
|
||||||
|
|
||||||
domhandler@^4.2.0:
|
domhandler@^4.2.0:
|
||||||
version "4.2.2"
|
version "4.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.2.tgz#e825d721d19a86b8c201a35264e226c678ee755f"
|
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.0.tgz#16c658c626cf966967e306f966b431f77d4a5626"
|
||||||
integrity sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==
|
integrity sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==
|
||||||
dependencies:
|
dependencies:
|
||||||
domelementtype "^2.2.0"
|
domelementtype "^2.2.0"
|
||||||
|
|
||||||
@ -3441,9 +3436,9 @@ ee-first@1.1.1:
|
|||||||
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
|
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
|
||||||
|
|
||||||
electron-to-chromium@^1.3.896:
|
electron-to-chromium@^1.3.896:
|
||||||
version "1.4.5"
|
version "1.4.8"
|
||||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.5.tgz#912e8fd1645edee2f0f212558f40916eb538b1f9"
|
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.8.tgz#e1b7752ac1a75e39b5dd90cc7e29ea08b351c484"
|
||||||
integrity sha512-YKaB+t8ul5crdh6OeqT2qXdxJGI0fAYb6/X8pDIyye+c3a7ndOCk5gVeKX+ABwivCGNS56vOAif3TN0qJMpEHw==
|
integrity sha512-Cu5+dbg55+1E3ohlsa8HT0s4b8D0gBewXEGG8s5wBl8ynWv60VuvYW25GpsOeTVXpulhyU/U8JYZH+yxASSJBQ==
|
||||||
|
|
||||||
emoji-regex@^8.0.0:
|
emoji-regex@^8.0.0:
|
||||||
version "8.0.0"
|
version "8.0.0"
|
||||||
@ -9417,9 +9412,9 @@ svgo@^2.1.0, svgo@^2.5.0, svgo@^2.7.0:
|
|||||||
stable "^0.1.8"
|
stable "^0.1.8"
|
||||||
|
|
||||||
table@^6.7.3:
|
table@^6.7.3:
|
||||||
version "6.7.3"
|
version "6.7.5"
|
||||||
resolved "https://registry.yarnpkg.com/table/-/table-6.7.3.tgz#255388439715a738391bd2ee4cbca89a4d05a9b7"
|
resolved "https://registry.yarnpkg.com/table/-/table-6.7.5.tgz#f04478c351ef3d8c7904f0e8be90a1b62417d238"
|
||||||
integrity sha512-5DkIxeA7XERBqMwJq0aHZOdMadBx4e6eDoFRuyT5VR82J0Ycg2DwM6GfA/EQAhJ+toRTaS1lIdSQCqgrmhPnlw==
|
integrity sha512-LFNeryOqiQHqCVKzhkymKwt6ozeRhlm8IL1mE8rNUurkir4heF6PzMyRgaTa4tlyPTGGgXuvVOF/OLWiH09Lqw==
|
||||||
dependencies:
|
dependencies:
|
||||||
ajv "^8.0.1"
|
ajv "^8.0.1"
|
||||||
lodash.truncate "^4.4.2"
|
lodash.truncate "^4.4.2"
|
||||||
@ -9769,9 +9764,9 @@ type-fest@^1.0.1:
|
|||||||
integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==
|
integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==
|
||||||
|
|
||||||
type-fest@^2.0.0, type-fest@^2.5.0:
|
type-fest@^2.0.0, type-fest@^2.5.0:
|
||||||
version "2.6.0"
|
version "2.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.6.0.tgz#e9f1e78c5f746ca97ccbb873c59aa16c3bf6b123"
|
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.8.0.tgz#39d7c9f9c508df8d6ce1cf5a966b0e6568dcc50d"
|
||||||
integrity sha512-XN1FDGGtaSDA6CFsCW5iolTQqFsnJ+ZF6JqSz0SqXoh4F8GY0xqUv5RYnTilpmL+sOH8OH4FX8tf9YyAPM2LDA==
|
integrity sha512-O+V9pAshf9C6loGaH0idwsmugI2LxVNR7DtS40gVo2EXZVYFgz9OuNtOhgHLdHdapOEWNdvz9Ob/eeuaWwwlxA==
|
||||||
|
|
||||||
type-is@~1.6.17, type-is@~1.6.18:
|
type-is@~1.6.17, type-is@~1.6.18:
|
||||||
version "1.6.18"
|
version "1.6.18"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user