feat(hub): add dark/light theme toggle with moon and sun icons
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
/** 中控主题:暗色(默认)/ 亮色,localStorage hub-theme */
|
||||
(function (global) {
|
||||
const KEY = "hub-theme";
|
||||
const META = { dark: "#0b0e18", light: "#e8eef5" };
|
||||
|
||||
function normalize(theme) {
|
||||
return theme === "light" ? "light" : "dark";
|
||||
}
|
||||
|
||||
function get() {
|
||||
try {
|
||||
return normalize(localStorage.getItem(KEY));
|
||||
} catch (_) {
|
||||
return "dark";
|
||||
}
|
||||
}
|
||||
|
||||
function apply(theme) {
|
||||
const t = normalize(theme);
|
||||
const root = document.documentElement;
|
||||
root.setAttribute("data-theme", t);
|
||||
try {
|
||||
localStorage.setItem(KEY, t);
|
||||
} catch (_) {}
|
||||
const meta = document.querySelector('meta[name="theme-color"]');
|
||||
if (meta) meta.setAttribute("content", META[t]);
|
||||
root.style.colorScheme = t;
|
||||
document.dispatchEvent(new CustomEvent("hub-theme-change", { detail: { theme: t } }));
|
||||
return t;
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
return apply(get() === "dark" ? "light" : "dark");
|
||||
}
|
||||
|
||||
function syncToggleUI(root) {
|
||||
const scope = root || document;
|
||||
scope.querySelectorAll(".theme-toggle-btn[data-theme-value]").forEach((btn) => {
|
||||
const on = btn.getAttribute("data-theme-value") === get();
|
||||
btn.classList.toggle("is-active", on);
|
||||
btn.setAttribute("aria-pressed", on ? "true" : "false");
|
||||
});
|
||||
}
|
||||
|
||||
function initToggleUI(root) {
|
||||
const scope = root || document;
|
||||
syncToggleUI(scope);
|
||||
scope.querySelectorAll(".theme-toggle-btn[data-theme-value]").forEach((btn) => {
|
||||
if (btn.dataset.themeBound === "1") return;
|
||||
btn.dataset.themeBound = "1";
|
||||
btn.addEventListener("click", () => {
|
||||
apply(btn.getAttribute("data-theme-value"));
|
||||
syncToggleUI(scope);
|
||||
});
|
||||
});
|
||||
document.addEventListener("hub-theme-change", () => syncToggleUI(scope));
|
||||
}
|
||||
|
||||
apply(get());
|
||||
global.HubTheme = { KEY, get, apply, toggle, syncToggleUI, initToggleUI };
|
||||
})(typeof window !== "undefined" ? window : globalThis);
|
||||
Reference in New Issue
Block a user