feat: 全局主题切换(浅色/深色/跟随系统)
- CSS 变量驱动的主题系统,所有颜色响应 data-theme 属性 - 新增语义化色彩 heading/secondary/tertiary,替换硬编码 text-white/text-gray-* - 右上角三态主题按钮(自动/浅色/深色),全局可用无需登录 - layout.tsx 内联脚本防闪烁 - 修复个人中心页面溢出无法滚动
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
export type Theme = "light" | "dark" | "system";
|
||||
|
||||
const STORAGE_KEY = "nowhatever-theme";
|
||||
|
||||
export function getStoredTheme(): Theme {
|
||||
if (typeof window === "undefined") return "system";
|
||||
return (localStorage.getItem(STORAGE_KEY) as Theme) || "system";
|
||||
}
|
||||
|
||||
export function setStoredTheme(theme: Theme): void {
|
||||
localStorage.setItem(STORAGE_KEY, theme);
|
||||
applyTheme(theme);
|
||||
}
|
||||
|
||||
function resolveTheme(theme: Theme): "light" | "dark" {
|
||||
if (theme !== "system") return theme;
|
||||
if (typeof window === "undefined") return "dark";
|
||||
return window.matchMedia("(prefers-color-scheme: light)").matches
|
||||
? "light"
|
||||
: "dark";
|
||||
}
|
||||
|
||||
export function applyTheme(theme: Theme): void {
|
||||
const resolved = resolveTheme(theme);
|
||||
document.documentElement.setAttribute("data-theme", resolved);
|
||||
}
|
||||
|
||||
export function initTheme(): void {
|
||||
const theme = getStoredTheme();
|
||||
applyTheme(theme);
|
||||
|
||||
if (theme === "system") {
|
||||
window
|
||||
.matchMedia("(prefers-color-scheme: light)")
|
||||
.addEventListener("change", () => applyTheme("system"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user