From 5b5554f99c895d53827cef9f69ddc611bda0816e Mon Sep 17 00:00:00 2001 From: daudix Date: Sun, 18 Aug 2024 16:04:34 +0300 Subject: [PATCH] Change theme switcher icon depending on current mode --- sass/_nav.scss | 16 ++++++ static/theme-switcher.js | 114 ++++++++++++++++++++++++--------------- 2 files changed, 87 insertions(+), 43 deletions(-) diff --git a/sass/_nav.scss b/sass/_nav.scss index 5068258..667d9ad 100644 --- a/sass/_nav.scss +++ b/sass/_nav.scss @@ -374,6 +374,22 @@ transform: scaleX(-100%); } } + + .icon.light { + $icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M8.004-.008a1 1 0 0 0-1 1v1a1 1 0 1 0 2 0v-1c0-.554-.445-1-1-1M3.053 2.035a1 1 0 0 0-.26.035.994.994 0 0 0-.45 1.672l.708.707a1 1 0 1 0 1.414-1.414l-.707-.707a1 1 0 0 0-.705-.293m9.9.012a1 1 0 0 0-.707.293l-.707.707a1 1 0 1 0 1.414 1.414l.707-.707a1 1 0 0 0-.707-1.707M8 4C5.785 4 4 5.785 4 8s1.785 4 4 4 4-1.785 4-4-1.785-4-4-4m0 2c1.098 0 2 .902 2 2s-.902 2-2 2-2-.902-2-2 .902-2 2-2m-7.004.984a1 1 0 1 0 0 2h1a1 1 0 1 0 0-2zM14 7c-.55 0-1 .45-1 1s.45 1 1 1h1c.55 0 1-.45 1-1s-.45-1-1-1zM3.748 11.234a1 1 0 0 0-.705.293l-.711.707a1.007 1.007 0 0 0 0 1.414c.39.391 1.027.391 1.418 0l.707-.707a1 1 0 0 0-.709-1.707m8.49.006q-.131 0-.261.033a1.01 1.01 0 0 0-.707.711 1 1 0 0 0 .261.965l.707.707a.995.995 0 0 0 1.672-.445 1 1 0 0 0-.258-.969l-.707-.707a1 1 0 0 0-.707-.295m-4.246 1.756c-.554 0-1 .445-1 1v1a1 1 0 1 0 2 0v-1a1 1 0 0 0-1-1'/%3E%3C/svg%3E"); + -webkit-mask-image: $icon; + mask-image: $icon; + } + + .icon.dark { + $icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M.918 8.004a7.072 7.072 0 0 0 14.102.793 1.01 1.01 0 0 0-.457-.957 1 1 0 0 0-1.063-.004 3.9 3.9 0 0 1-2.031.578 3.89 3.89 0 0 1-3.883-3.883c0-.715.203-1.422.578-2.031a1 1 0 0 0-.004-1.062c-.207-.32-.578-.5-.957-.458A7.07 7.07 0 0 0 .918 8.004M5.586 4.53a5.877 5.877 0 0 0 8.965 5.004l-1.52-.96a5.09 5.09 0 0 1-5.035 4.507 5.09 5.09 0 0 1-5.078-5.078 5.09 5.09 0 0 1 4.508-5.035l-.961-1.52a5.9 5.9 0 0 0-.88 3.082m0 0'/%3E%3C/svg%3E"); + -webkit-mask-image: $icon; + mask-image: $icon; + + :root[dir*="rtl"] & { + transform: scaleX(-100%); + } + } } } diff --git a/static/theme-switcher.js b/static/theme-switcher.js index 165ee81..6683383 100644 --- a/static/theme-switcher.js +++ b/static/theme-switcher.js @@ -1,54 +1,82 @@ +// Initial code taken from https://github.com/welpo/tabi/blob/6ba0e541046b1f0b33fa177d5569cebe9d76bf4c/static/js/initializeTheme.js +// and https://github.com/welpo/tabi/blob/6ba0e541046b1f0b33fa177d5569cebe9d76bf4c/static/js/themeSwitcher.js + +// Theme Initialization (function () { - // Get the default theme from the HTML data-theme attribute. - const defaultTheme = document.documentElement.getAttribute("data-theme"); + // Get the default theme from the HTML data-theme attribute. + const defaultTheme = document.documentElement.getAttribute("data-theme"); - // Set the data-default-theme attribute only if defaultTheme is not null. - if (defaultTheme) { - document.documentElement.setAttribute("data-default-theme", defaultTheme); - } + // Set the data-default-theme attribute only if defaultTheme is not null. + if (defaultTheme) { + document.documentElement.setAttribute("data-default-theme", defaultTheme); + } - // Attempt to retrieve the current theme from the browser's local storage. - const storedTheme = localStorage.getItem("theme"); + // Attempt to retrieve the current theme from the browser's local storage. + const storedTheme = localStorage.getItem("theme"); - if (storedTheme && storedTheme !== "system") { - document.documentElement.setAttribute("data-theme", storedTheme); - } else if (defaultTheme && storedTheme !== "system") { - document.documentElement.setAttribute("data-theme", defaultTheme); - } else { - // If no theme is found in local storage and no default theme is set, CSS handles the theme. - document.documentElement.removeAttribute("data-theme"); - } + if (storedTheme && storedTheme !== "system") { + document.documentElement.setAttribute("data-theme", storedTheme); + } else if (defaultTheme && storedTheme !== "system") { + document.documentElement.setAttribute("data-theme", defaultTheme); + } else { + // If no theme is found in local storage and no default theme is set, hand over control to the CSS. + document.documentElement.removeAttribute("data-theme"); + } + + // Expose defaultTheme to the outer scope. + window.defaultTheme = defaultTheme; })(); -const defaultTheme = document.documentElement.getAttribute("data-default-theme"); +// Deferred Icon Update and Theme Switching +document.addEventListener("DOMContentLoaded", function () { + function setTheme(theme, saveToLocalStorage = false) { + if (theme === "system") { + document.documentElement.removeAttribute("data-theme"); + } else { + document.documentElement.setAttribute("data-theme", theme); + } -function setTheme(theme, saveToLocalStorage = false) { - if (theme === "system") { - document.documentElement.removeAttribute("data-theme"); - } else { - document.documentElement.setAttribute("data-theme", theme); - } + if (saveToLocalStorage) { + localStorage.setItem("theme", theme); + } else { + localStorage.removeItem("theme"); + } - if (saveToLocalStorage) { - localStorage.setItem("theme", theme); - } else { - localStorage.removeItem("theme"); - } + // Update icon class based on the selected theme. + updateIconClass(theme); + } - // Dispatch a custom event for comment systems. - window.dispatchEvent(new CustomEvent("themeChanged", { detail: { theme } })); -} + function resetTheme() { + // Reset the theme to the default or system preference if no default is set. + setTheme(window.defaultTheme || "system"); + } -function resetTheme() { - // Reset the theme to the default or system preference if no default is set. - setTheme(defaultTheme || "system"); -} + function switchTheme(theme) { + if (theme === "system") { + resetTheme(); + } else { + setTheme(theme, true); + } + } -// Functions connected to buttons via `onclick` attributes. -function switchTheme(theme) { - if (theme === "system") { - resetTheme(); - } else { - setTheme(theme, true); - } -} + function updateIconClass(theme) { + const iconElement = document.querySelector("#theme-switcher summary i.icon"); + + // Remove any existing theme classes + iconElement.classList.remove("light", "dark"); + + // Add the appropriate class based on the selected theme + if (theme === "light") { + iconElement.classList.add("light"); + } else if (theme === "dark") { + iconElement.classList.add("dark"); + } + } + + // Update icon class on page load based on current theme + const currentTheme = localStorage.getItem("theme") || window.defaultTheme || "system"; + updateIconClass(currentTheme); + + // Make the switchTheme function accessible globally + window.switchTheme = switchTheme; +});