From 2c95997a0c49c9ffbd9c6e906b0996aeaf470d6c Mon Sep 17 00:00:00 2001 From: Alexandre Iooss Date: Sat, 1 Jun 2024 19:07:01 +0200 Subject: [PATCH 1/5] Add color mode switcher --- assets/js/color_mode_switcher.js | 50 ++++++++++++++++++++++++++++++++ templates/base.html | 4 ++- templates/components/navbar.html | 11 +++++++ vite.config.js | 1 + 4 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 assets/js/color_mode_switcher.js diff --git a/assets/js/color_mode_switcher.js b/assets/js/color_mode_switcher.js new file mode 100644 index 0000000..b30a4df --- /dev/null +++ b/assets/js/color_mode_switcher.js @@ -0,0 +1,50 @@ +"use strict"; + +/** + * Get user preferred theme from their past choice or browser + * @returns {String} User preferred theme + */ +function getPreferredTheme() { + const storedTheme = localStorage.getItem("theme"); + if (storedTheme) { + return storedTheme; + } + // Firefox with 'resistFingerprint' activated always returns light + return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"; +} + +/** + * Update navbar icon to match given theme. + * @param {String} theme - 'dark' or 'light' + */ +function showActiveTheme(theme) { + const activeThemeIcon = document.querySelector(".theme-switch i.fas"); + activeThemeIcon.classList.toggle("fa-moon", theme === "dark"); + activeThemeIcon.classList.toggle("fa-sun", theme !== "dark"); +} + +// Change body theme early to prevent flash +let currentTheme = getPreferredTheme(); +document.documentElement.setAttribute("data-bs-theme", currentTheme); + +// On browser color-scheme change, update +window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => { + currentTheme = getPreferredTheme(); + document.documentElement.setAttribute("data-bs-theme", currentTheme); + showActiveTheme(currentTheme); +}); + +window.addEventListener("load", () => { + showActiveTheme(currentTheme); + + // On button click, switch + document.querySelectorAll(".theme-switch").forEach(e => { + e.addEventListener("click", ev => { + currentTheme = currentTheme === "light" ? "dark" : "light"; + document.documentElement.setAttribute("data-bs-theme", currentTheme); + localStorage.setItem("theme", currentTheme); + showActiveTheme(currentTheme); + ev.preventDefault(); + }); + }); +}); diff --git a/templates/base.html b/templates/base.html index 7804c06..fadd017 100644 --- a/templates/base.html +++ b/templates/base.html @@ -14,6 +14,8 @@ {{ Plugins.styles }} + {{ Assets.js("assets/js/color_mode_switcher.js", defer=False) }} +