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:
2026-09-14 11:57:41 +08:00
parent 2b6eb97bc9
commit 9aa702b8cc
7 changed files with 290 additions and 42 deletions

View File

@ -878,9 +878,13 @@ html[data-bg='on'] .app-shell > * {
*
* 用深色玻璃而不是白色玻璃:白字压在深色上才有对比度。α=0.72 + blur(18px)。
*/
html[data-bg='on'] .bg-chrome-900,
html[data-bg='on'] .app-shell > .bg-chrome-900 {
background-color: rgb(var(--c-chrome-900) / 0.72);
/*
* 导航在壁纸模式下不再单独着色:它走 `--nav-bg` 令牌
* (浅色主题=白玻璃、深色主题=深玻璃,见文件末尾的令牌块)。
* 原先这里写死深玻璃 —— 那正是用户说的"导航栏为什么还是黑色"。
*/
html[data-bg='on'] .nav-rail,
html[data-bg='on'] .narrow-nav {
backdrop-filter: blur(18px) saturate(1.4);
-webkit-backdrop-filter: blur(18px) saturate(1.4);
}
@ -983,7 +987,9 @@ select,
margin: 0 10px calc(10px + env(safe-area-inset-bottom));
border-radius: var(--radius-card, 14px);
border: 1px solid rgb(255 255 255 / 0.12);
background-color: rgb(15 23 42 / 0.82);
/* 底色走 --nav-bg(浅色主题=白玻璃,深色主题=深玻璃) */
background-color: rgb(var(--nav-bg));
border: 1px solid rgb(var(--nav-border));
backdrop-filter: blur(18px) saturate(1.5);
-webkit-backdrop-filter: blur(18px) saturate(1.5);
box-shadow: 0 10px 30px rgb(0 0 0 / 0.35);
@ -1010,9 +1016,36 @@ select,
}
}
html.view-switch .app-shell > *,
html.view-switch .narrow-shell > * {
animation: pane-in 220ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
/*
* ★ 只动**主内容区**,不动侧栏与列表(2026-09-14 用户:「部分动画十分不合理,
* 会导致页面大范围的闪动,且不能让人自然的把注意力集中在将要出现的页面上」)。
*
* 原先这条把外壳的**所有**直接子面板一起做入场动画 ⇒ 切一次视图整屏都在动,
* 眼睛不知道该看哪里,观感就是"闪"。现在只让将要出现的那一页淡入,
* 而且幅度从 translateY(6px)+scale 收到 4px、不加缩放(缩放最容易让人觉得闪)。
*/
@keyframes pane-in {
from {
opacity: 0;
transform: translateY(4px);
}
to {
opacity: 1;
transform: none;
}
}
/*
* ★ 视图切换**不再做整面板入场动画**(2026-09-14 用户:「部分动画十分不合理,
* 会导致页面大范围的闪动,且不能让人自然的把注意力集中在将要出现的页面上」)。
*
* 我先是从"所有面板一起动"改成"只动主内容区",但试下来仍然不对:页面级淡入
* 会让**已经在那儿的框架**也一起暗一下,观感还是闪。所以这一档整体删掉 ——
* 只保留**局部**、有明确语义的动效(日历翻页、菜单展开、背景图淡入)。
* 骨架不动,注意力自然落在变化的那块内容上。
*/
html.view-switch .pane-enter {
animation: pane-in 140ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
/* 菜单/建议列表:轻微放大淡入,避免"啪"地出现 */
@ -1151,3 +1184,73 @@ html.view-switch .glass-control,
flex: 1 1 0%;
min-width: 0;
}
/*
* ═══════════════════════════════════════════════════════════════════
* 导航配色令牌(浅色玻璃 + 深字,深色主题自动反色)
*
* 用户(2026-09-14):「那你为什么不把白字换成黑字或者自动反色或者描边呢?」
* —— 他是对的。这个应用是浅色底 + 深字,导航却是全页唯一一块黑的:
* 我上一轮为了"白字对比度"把它做成深玻璃,那是**用错误的方式解决对比度**,
* 真正的割裂就在这儿。深色底只应该是深色主题下的样子。
*
* 所以导航底色/文字都走令牌:
* - 浅色主题:白玻璃(0.72)+ 深字;
* - 深色主题(.dark):深玻璃(0.72)+ 亮字。
* 这样"对比度"是**按主题算出来的**,而不是靠把某一块永久压黑。
*/
:root {
--nav-bg: 255 255 255 / 0.72;
--nav-fg: 15 23 42;
--nav-fg-muted: 71 85 105;
--nav-hover-bg: 15 23 42 / 0.07;
--nav-active-bg: 219 234 254;
--nav-active-fg: 30 64 175;
--nav-border: 15 23 42 / 0.08;
}
.dark {
--nav-bg: 15 23 42 / 0.72;
--nav-fg: 248 250 252;
--nav-fg-muted: 148 163 184;
--nav-hover-bg: 255 255 255 / 0.08;
--nav-active-bg: 30 58 138;
--nav-active-fg: 219 234 254;
--nav-border: 255 255 255 / 0.1;
}
.nav-rail {
background-color: rgb(var(--nav-bg));
border-right: 1px solid rgb(var(--nav-border));
}
.nav-item {
color: rgb(var(--nav-fg-muted));
transition: background-color 150ms, color 150ms;
}
.nav-item:hover {
background-color: rgb(var(--nav-hover-bg));
color: rgb(var(--nav-fg));
}
.nav-item[data-active='true'] {
background-color: rgb(var(--nav-active-bg));
color: rgb(var(--nav-active-fg));
}
/* 底部导航条:与侧栏同一套令牌(深色主题才变深) */
.narrow-nav {
background-color: rgb(var(--nav-bg)) !important;
}
/*
* ⚠ 这里曾经写死过一份深色导航的字面值(因为实测"深色下文字没变")。
* 那是**误判**:`.nav-item` 有 `transition: color .15s`,我在切换 .dark 之后
* 立刻读 computed color,拿到的是过渡的**起点**(浅色值)⇒ 对比度算出来只有 2.36。
* 决定性证据是:连内联 style 都"改不动"它 —— 级联不可能这样,只可能是还在过渡中。
* 等 400ms 再量就是正常的(见 test/manual/nav-contrast-verify.mjs)。
* 所以深色这一档仍然只用上面的 .dark 令牌块,一处定义。
*/