fix(webui): 导航改"按主题的玻璃"(浅色白玻璃+深字)+ 去掉整屏闪的入场动画
用户两句话:
「那你为什么不把白字换成黑字或者自动反色或者描边呢?」
「部分动画十分不合理,会导致页面大范围的闪动,且不能让人自然的把注意力集中在
将要出现的页面上」
## ① 导航:他说得对,我之前是用错误的方式解决对比度
这个应用是**浅色底 + 深字**,导航却是全页唯一一块黑的 —— 那才是"割裂"。我上一轮
为了"白字对比度"把它做成深玻璃,等于**把一块地方永久压黑**来回避问题。
现在导航底色/文字全部走令牌,按主题切换:
浅色:白玻璃 rgb(255 255 255 / .72) + 深字 #475569 → 对比度 7.48:1
深色:深玻璃 rgb(15 23 42 / .72) + 亮字 #94a3b8 → 自动反色
组件侧改成 `.nav-rail` / `.nav-item[data-active]` 令牌类(Sidebar 与 NarrowNav 同一套)。
同时删掉壁纸模式里写死的深玻璃规则 —— 那条正是"为什么还是黑色"。
## ② 动画:整面板入场删掉
先是从"所有面板一起动"改成"只动主内容区",试下来仍然不对:页面级淡入会把
**已经在那儿的框架**也一起暗一下,观感还是闪。所以这一档整体删掉,只保留局部、
有明确语义的动效(日历翻页、菜单展开)。实测切视图时 `animatedOnSwitch = 0`。
骨架不动,注意力自然落在变化的那块内容上。
## ③ 一条我自己的误判(值得记下)
深色主题下我量到导航文字对比度只有 2.36,一度以为是变量/级联的问题,还写死了一份
深色字面值。**那是误判**:`.nav-item` 有 `transition: color .15s`,我在切主题后
**立刻**读 computed color,拿到的是过渡的**起点**(浅色值)。决定性证据是连内联
`style.color` 都"改不动"它 —— 级联不可能这样,只可能是还在过渡中。等 400ms 再量就正常。
写死的那份已撤掉,并在 CSS 里留下说明;新判据 `test/manual/nav-contrast-verify.mjs`
用 WCAG 比值量对比度(不是"颜色是不是黑的"),每次读之前等 400ms。
背景套件 32 条全绿(含"导航走令牌 + 两套令牌都在")。
This commit is contained in:
@ -234,13 +234,21 @@ check('新组件未使用未映射色族', unmapped.length === 0, unmapped.join(
|
||||
* 现在的契约:**深色玻璃**(白字要对比度,所以不用白色玻璃),
|
||||
* α 落在 [0.6, 0.9]:太透读不清,太实就退回那块黑 slab。
|
||||
*/
|
||||
const navAlpha = Number(
|
||||
(css.match(/html\[data-bg='on'\] \.bg-chrome-900,[\s\S]{0,200}?rgb\(var\(--c-chrome-900\) \/ ([\d.]+)\)/) || [])[1]
|
||||
);
|
||||
const navGlass = /html\[data-bg='on'\] \.bg-chrome-900,[\s\S]{0,240}backdrop-filter: blur\(/.test(css);
|
||||
check('导航栏是深色玻璃(α 在 0.6–0.9,读得清又不挡壁纸)',
|
||||
Number.isFinite(navAlpha) && navAlpha >= 0.6 && navAlpha <= 0.9, `α=${navAlpha}`);
|
||||
check('导航栏参与模糊(玻璃的必要条件)', navGlass);
|
||||
/*
|
||||
* ★ 导航这条改过三次,最后一次才对(2026-09-14 用户:「那你为什么不把白字换成
|
||||
* 黑字或者自动反色或者描边呢?」):
|
||||
* ① 不透明实心(最早)
|
||||
* ② 深色玻璃(我为了"白字对比度"做的 —— 用错误的方式解决对比度,全页唯一一块黑)
|
||||
* ③ **按主题走的令牌**:浅色=白玻璃+深字、深色=深玻璃+亮字
|
||||
* 判据因此不再断言某个固定颜色,而是断言"走令牌"这件事 + 对比度由
|
||||
* test/manual/nav-contrast-verify.mjs 用 WCAG 比值来量。
|
||||
*/
|
||||
check('导航底色走 --nav-bg 令牌(浅色/深色各一套,不写死)',
|
||||
/\.nav-rail \{[\s\S]{0,80}background-color: rgb\(var\(--nav-bg\)\)/.test(css) &&
|
||||
/\.nav-item \{[\s\S]{0,80}color: rgb\(var\(--nav-fg-muted\)\)/.test(css));
|
||||
check('浅色与深色两套令牌都定义了(自动反色)',
|
||||
/--nav-bg: 255 255 255 \/ 0\.72/.test(css) && /--nav-bg: 15 23 42 \/ 0\.72/.test(css));
|
||||
check('导航在壁纸模式下仍参与模糊', /html\[data-bg='on'\] \.nav-rail,[\s\S]{0,200}backdrop-filter: blur\(/.test(css));
|
||||
check('内层面板自带圆角(不靠裁剪,否则与滚动冲突)',
|
||||
/\.comm-pane > \*:not\(\[data-testid='comm-tabs'\]\) \{[\s\S]{0,80}border-radius: var\(--radius-card\)/.test(css));
|
||||
/*
|
||||
@ -255,9 +263,13 @@ check('新组件未使用未映射色族', unmapped.length === 0, unmapped.join(
|
||||
/(?<!data-bg='on'\] )\.app-shell > \* \{[\s\S]{0,160}border-radius: var\(--radius-card\)/.test(css));
|
||||
check('窄屏内容面板也浮起来(圆角)',
|
||||
/\.narrow-shell > \*:not\(\.narrow-nav\) \{[\s\S]{0,80}border-radius: var\(--radius-card\)/.test(css));
|
||||
// 判据用 `[^}]*`(限定在 `.narrow-nav` 这一条规则内)而不是固定字符窗口:
|
||||
// 原来写的是 {0,220}/{0,120},往规则里加一行注释(改配色时很容易加)就会
|
||||
// 把 backdrop-filter 挤出窗口,于是断言变红而 CSS 其实完全正确 —— 实测踩到过。
|
||||
// 要表达的语义是「这条规则里有这两个声明」,不是「它们在 N 个字符以内」。
|
||||
check('窄屏底部导航是悬浮玻璃(留缝 + 模糊)',
|
||||
/\.narrow-nav \{[\s\S]{0,220}backdrop-filter: blur\(/.test(css) &&
|
||||
/\.narrow-nav \{[\s\S]{0,120}margin: 0 10px/.test(css));
|
||||
/\.narrow-nav \{[^}]*backdrop-filter: blur\(/.test(css) &&
|
||||
/\.narrow-nav \{[^}]*margin: 0 10px/.test(css));
|
||||
|
||||
console.log(`\n背景:${pass} 通过${fail ? `,${fail} 失败` : ''}`);
|
||||
process.exit(fail ? 1 : 0);
|
||||
|
||||
Reference in New Issue
Block a user