mirror of
https://github.com/imfing/hextra.git
synced 2025-08-23 13:26:54 -04:00
feat: add 'system' inside the theme toggle (#766)
* feat: add 'system' inside the theme toggle * chore: generate hugo_stats.json * fix: missing css * chore: reorganize code * feat: menu * chore: simplify * chore: some i18n * review * fix: remove replace
This commit is contained in:

committed by
GitHub

parent
363b1e50ff
commit
18a9335d4b
File diff suppressed because one or more lines are too long
@@ -3,8 +3,11 @@
|
||||
languageSwitchers.forEach((switcher) => {
|
||||
switcher.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
switcher.dataset.state = switcher.dataset.state === 'open' ? 'closed' : 'open';
|
||||
|
||||
const optionsElement = switcher.nextElementSibling;
|
||||
|
||||
optionsElement.classList.toggle('hx:hidden');
|
||||
|
||||
// Calculate the position of a language options element.
|
||||
|
@@ -3,49 +3,116 @@
|
||||
const defaultTheme = '{{ site.Params.theme.default | default `system`}}'
|
||||
|
||||
const themeToggleButtons = document.querySelectorAll(".hextra-theme-toggle");
|
||||
const themeToggleOptions = document.querySelectorAll(".hextra-theme-toggle-options p");
|
||||
|
||||
// Change the icons of the buttons based on previous settings or system theme
|
||||
if (
|
||||
localStorage.getItem("color-theme") === "dark" ||
|
||||
(!("color-theme" in localStorage) &&
|
||||
((window.matchMedia("(prefers-color-scheme: dark)").matches && defaultTheme === "system") || defaultTheme === "dark"))
|
||||
) {
|
||||
themeToggleButtons.forEach((el) => el.dataset.theme = "dark");
|
||||
} else {
|
||||
themeToggleButtons.forEach((el) => el.dataset.theme = "light");
|
||||
function setSystemTheme() {
|
||||
const prefersColorScheme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
||||
|
||||
document.documentElement.classList.remove("dark", "light");
|
||||
document.documentElement.classList.add(prefersColorScheme);
|
||||
|
||||
document.documentElement.style.colorScheme = prefersColorScheme;
|
||||
}
|
||||
|
||||
function applyTheme(theme) {
|
||||
themeToggleButtons.forEach((btn) => btn.parentElement.dataset.theme = theme );
|
||||
|
||||
localStorage.setItem("color-theme", theme);
|
||||
}
|
||||
|
||||
function switchTheme(theme) {
|
||||
switch (theme) {
|
||||
case "light":
|
||||
document.documentElement.classList.remove("dark");
|
||||
document.documentElement.classList.add(theme);
|
||||
document.documentElement.style.colorScheme = theme;
|
||||
|
||||
applyTheme(theme);
|
||||
|
||||
break;
|
||||
case "dark":
|
||||
document.documentElement.classList.remove("light");
|
||||
document.documentElement.classList.add(theme);
|
||||
document.documentElement.style.colorScheme = theme;
|
||||
|
||||
applyTheme(theme);
|
||||
|
||||
break;
|
||||
default:
|
||||
setSystemTheme();
|
||||
applyTheme("system");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const colorTheme = "color-theme" in localStorage ? localStorage.getItem("color-theme") : defaultTheme;
|
||||
switchTheme(colorTheme);
|
||||
|
||||
// Add click event handler to the menu items.
|
||||
themeToggleOptions.forEach((option) => {
|
||||
option.addEventListener("click", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
switchTheme(option.dataset.item);
|
||||
})
|
||||
})
|
||||
|
||||
// Add click event handler to the buttons
|
||||
themeToggleButtons.forEach((el) => {
|
||||
el.addEventListener("click", function () {
|
||||
if (localStorage.getItem("color-theme")) {
|
||||
if (localStorage.getItem("color-theme") === "light") {
|
||||
setDarkTheme();
|
||||
localStorage.setItem("color-theme", "dark");
|
||||
} else {
|
||||
setLightTheme();
|
||||
localStorage.setItem("color-theme", "light");
|
||||
}
|
||||
} else {
|
||||
if (document.documentElement.classList.contains("dark")) {
|
||||
setLightTheme();
|
||||
localStorage.setItem("color-theme", "light");
|
||||
} else {
|
||||
setDarkTheme();
|
||||
localStorage.setItem("color-theme", "dark");
|
||||
}
|
||||
themeToggleButtons.forEach((toggler) => {
|
||||
toggler.addEventListener("click", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
const optionsElement = toggler.nextElementSibling;
|
||||
|
||||
optionsElement.classList.toggle('hx:hidden');
|
||||
|
||||
// Calculate the position of a language options element.
|
||||
const switcherRect = toggler.getBoundingClientRect();
|
||||
|
||||
// Must be called before optionsElement.clientWidth.
|
||||
optionsElement.style.minWidth = `${Math.max(switcherRect.width, 50)}px`;
|
||||
|
||||
const isOnTop = toggler.dataset.location === 'top';
|
||||
const isOnBottom = toggler.dataset.location === 'bottom';
|
||||
const isOnBottomRight = toggler.dataset.location === 'bottom-right';
|
||||
const isRTL = document.body.dir === 'rtl'
|
||||
|
||||
// Stuck on the left side of the switcher.
|
||||
let translateX = switcherRect.left;
|
||||
|
||||
if (isOnTop && !isRTL || isOnBottom && isRTL || isOnBottomRight && !isRTL) {
|
||||
// Stuck on the right side of the switcher.
|
||||
translateX = switcherRect.right - optionsElement.clientWidth;
|
||||
}
|
||||
el.dataset.theme = document.documentElement.classList.contains("dark") ? "dark" : "light";
|
||||
|
||||
// Stuck on the top of the switcher.
|
||||
let translateY = switcherRect.top - window.innerHeight - 15;
|
||||
|
||||
if (isOnTop) {
|
||||
// Stuck on the bottom of the switcher.
|
||||
translateY = switcherRect.top - window.innerHeight + 150;
|
||||
}
|
||||
|
||||
optionsElement.style.transform = `translate3d(${translateX}px, ${translateY}px, 0)`;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Dismiss the menu when clicking outside
|
||||
document.addEventListener('click', (e) => {
|
||||
if (e.target.closest('.hextra-theme-toggle') === null) {
|
||||
themeToggleButtons.forEach((toggler) => {
|
||||
toggler.dataset.state = 'closed';
|
||||
toggler.nextElementSibling.classList.add('hx:hidden');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Listen for system theme changes
|
||||
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (e) => {
|
||||
if (defaultTheme === "system" && !("color-theme" in localStorage)) {
|
||||
e.matches ? setDarkTheme() : setLightTheme();
|
||||
themeToggleButtons.forEach((el) =>
|
||||
el.dataset.theme = document.documentElement.classList.contains("dark") ? "dark" : "light"
|
||||
);
|
||||
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => {
|
||||
if (localStorage.getItem("color-theme") === "system") {
|
||||
setSystemTheme();
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
Reference in New Issue
Block a user