feat(theme): 主题三态偏好模型,默认跟随系统自动切换暗黑模式
- 新增 src/lib/theme.ts:三态偏好单一真源
(system/light/dark,无存储值默认跟随系统)
- ThemeToggle 改三态循环(Monitor→Sun→Moon):
实时监听 prefers-color-scheme(仅 system 档生效)
+ storage 跨标签页同步;尺寸位置不变
- layout.tsx FOUC 内联脚本支持 system 档,
首帧前解析避免闪烁
- e2e 视觉回归 L2 改用 test.use({ colorScheme }) 驱动
(事后 setAttribute 存在被挂载效果覆盖的竞态)
- header.test.tsx lucide 白名单补 Monitor
- CLAUDE.md 同步三态语义与 variant 踩坑
- 新增 scripts/audit/theme-system-verify.mjs
(55 断言:首帧无闪烁/循环/实时跟随/旧值兼容/
污染回退/6 路由冒烟)
验证:单测 131 套件 1662 通过 0 失败;
tsc 0 错;eslint 0 错;next build 通过;
运行时 55/55 PASS(dogfood-output/theme-system-verify/)
This commit is contained in:
+6
-3
@@ -170,11 +170,14 @@ export default async function RootLayout({
|
||||
suppressHydrationWarning
|
||||
>
|
||||
<head>
|
||||
{/* 主题防 FOUC(暗黑模式 Phase 1 基础设施):首帧前同步读取 localStorage 设置 data-theme,
|
||||
无存储值时保持浅色(默认)。当前无切换 UI,仅作挂载点,未来切换器写入 novalon-theme 即可生效。 */}
|
||||
{/* 主题防 FOUC:首帧前同步解析偏好并写入 data-theme,避免刷新闪白/闪黑。
|
||||
三档语义(与 src/lib/theme.ts 严格一致,改动时两处必须同步):
|
||||
'light' | 'dark' → 用户显式选择,直接生效
|
||||
'system' | 无值 → 跟随操作系统 prefers-color-scheme
|
||||
显式选择优先于系统偏好;localStorage 不可用(隐私模式)时兜底浅色。 */}
|
||||
<script
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `(function(){try{var t=localStorage.getItem('novalon-theme');if(t==='dark'||t==='light'){document.documentElement.setAttribute('data-theme',t);}}catch(e){}})();`,
|
||||
__html: `(function(){try{var p=localStorage.getItem('novalon-theme');if(p!=='light'&&p!=='dark'&&p!=='system'){p='system';}var t=p;if(p==='system'){t=(window.matchMedia&&window.matchMedia('(prefers-color-scheme: dark)').matches)?'dark':'light';}document.documentElement.setAttribute('data-theme',t);}catch(e){try{document.documentElement.setAttribute('data-theme','light');}catch(e2){}}})();`,
|
||||
}}
|
||||
/>
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
|
||||
Reference in New Issue
Block a user