feat(webui): 导航合并 + 悬浮玻璃 + 页面动画 + 控件档透明度 + 圆角无条件生效
用户四封信(同一线索)提的六件事,都在这里: ## ① 导航合并(「导航栏的内容有点多了」) 收件箱/发件箱/授权 → 一项「通信」,进去由**内部页签**区分(CommTabs); 新建 → 「通信」页内**悬浮圆形加号**(ComposeFab);导航只剩 通信/日历/联系人; 管理 → 合进「我的」,管理员在页面**最下面**看得到(非管理员不渲染,不是禁用)。 `viewMode` 仍是原来那三个值(几十处调用点不用改),新增 `commTab` 记住上次用的子页签; 通信项的徽标 = 未读 + 待决策(授权信息不能因为合并而消失)。 ## ② 窄屏底部导航:悬浮玻璃(「还是固定底部延伸,没有玻璃效果,也没有悬浮」) 原来是 `border-t bg-chrome-900` 通栏贴底。改成:左右/离底各留 10px、圆角、 深色半透明 + `blur(18px)`、投影,安全区并入下外边距。 ## ③ 页面动画(「页面极度缺少动画,所有页面都是直接出现」) 在 `<html>` 上挂一个短命类触发外壳直接子面板的入场动画。**没有用 key 重挂载**: 面板是 flex 链上的一环,套 wrapper 会改掉 flex 传递(窄屏覆盖层最先坏)。 并且尊重 `prefers-reduced-motion`(关了就一点都不动)。 ## ④ 控件档透明度(「复选框和地址猜测项…他们才是真正需要拉低透明度的地方」) 新增第三档 `--bg-glass-control`(0.5/0.55):授权多选胶囊、地址建议菜单。 三档递减:正文面 0.88 > 嵌套 0.82 > 控件 0.5。 ## ⑤ 打底 vs 透明(上一封「该打底的地方透了、该透的空白处糊了」) 正文面回到 0.88(读得清优先)、空白/页面底透明**且不模糊**、面板模糊降到 10px。 ## ⑥ 圆角与玻璃**无条件**生效(「大面积缺失圆角与玻璃效果…都是硬截断」) 根因:`.app-shell` 的留缝/圆角/投影原先全写在 `html[data-bg='on']` 里 ⇒ **没开壁纸的账号**看到的是硬边不透明面板。现在几何下沉为无条件基线, 壁纸相关的加强仍叠加在上面。窄屏内容面板同样浮起来。 ## 判据 - `test/nav-merge.test.mjs` 8 条(含自检:重构前的写法必须判红)—— 改完跑老套件 254 条**全绿却一条都没测导航结构**,结构改动必须自带判据。 - `test/manual/nav-restructure-verify.mjs`:真浏览器 9 条(导航项数、页签切换真的换内容、 加号 56×56 且 `elementFromPoint` 命中自己、我的页底部管理入口在退出登录之后、 控件档 α=0.5 对正文面 α=0.88 的反向对照)。 - `test/manual/narrow-glass-verify.mjs` 6 条:悬浮几何(三边留缝 10px、圆角 14px、 缝隙处命中的是页面底 ⇒ 真的浮着)、玻璃(α=0.82 + blur18)、触摸高度最小 49px、 动画真的在跑(静止时 `animationName=none`,切换后 =pane-in)且 reduced-motion 下不动。 - `test/background.test.mjs`:把三条**过时判据**(早前那版"越透越好")按现行契约重写 —— 旧判据留着只会把我拽回错误方向。30 条全绿。 ## 顺带 窄屏探针原先只调视口、**没模拟触屏**,于是 `(hover: hover)` 仍为真, 把「悬停才显形的次要动作」误报成透明 —— 差点去"修"一个本来就对的规则。 已改成 hasTouch + isMobile + DPR 的触屏上下文,且收尾只关自己的 context (CDP 连的是共享 Chromium,`browser.close()` 会把别人的标签页一起关掉)。
This commit is contained in:
@ -228,7 +228,7 @@
|
||||
--bg-dim: 12%;
|
||||
--bg-blur: 4px;
|
||||
/* 玻璃面板的不透明度:背景越花,面板需要越实才读得动。 */
|
||||
--bg-glass: 0.45;
|
||||
--bg-glass: 0.88;
|
||||
/*
|
||||
* 嵌套面板那一层的不透明度。
|
||||
*
|
||||
@ -240,9 +240,18 @@
|
||||
* 原则是「玻璃只该出现一次」:最外层负责遮罩与模糊,里面几层只留一点点
|
||||
* 色调(保住正文对比度),第三层起直接透明(见下面 data-bg='on' 的规则)。
|
||||
*/
|
||||
--bg-glass-inner: 0.22;
|
||||
--bg-glass-inner: 0.82;
|
||||
/*
|
||||
* 控件级透度:复选框、选项胶囊、地址建议菜单这类**小控件**。
|
||||
*
|
||||
* 用户第三轮的原话:「复选框和地址猜测项的透明度问题还没改,他们才是真正需要
|
||||
* 拉低透明度的地方」。也就是说:承载正文的大面必须够实(读得清),
|
||||
* 而这些小块本身没有大段文字,透一点反而好看 —— 壁纸透过它们,界面才有层次。
|
||||
* 三档从实到透:正文面(--bg-glass) > 嵌套卡(--bg-glass-inner) > 控件(--bg-glass-control)。
|
||||
*/
|
||||
--bg-glass-control: 0.5;
|
||||
/* 面板的朦胧感(与壁纸自身的 --bg-blur 分开:那层给照片打底,这层给面板) */
|
||||
--bg-blur-panel: 18px;
|
||||
--bg-blur-panel: 10px;
|
||||
/* 浮动面板之间的缝隙:壁纸从缝隙里露出来,是圆角化玻璃化的关键 */
|
||||
--pane-gap: 10px;
|
||||
|
||||
@ -349,8 +358,9 @@
|
||||
*/
|
||||
--bg-scrim: 0 0 0;
|
||||
/* 深色下面板要更实:背景亮部与深色卡片对比过强时,文字会显得发灰。 */
|
||||
--bg-glass: 0.5;
|
||||
--bg-glass-inner: 0.26;
|
||||
--bg-glass: 0.9;
|
||||
--bg-glass-inner: 0.84;
|
||||
--bg-glass-control: 0.55;
|
||||
|
||||
/*
|
||||
* 深色下的层次靠「边框亮于底」而不是阴影。
|
||||
@ -721,6 +731,21 @@ html[data-bg='on'] body,
|
||||
html[data-bg='on'] .bg-gray-50,
|
||||
html[data-bg='on'] .bg-slate-100 {
|
||||
background-color: transparent;
|
||||
/* 空白区不模糊:壁纸在这里要清晰可辨(用户:"真正该透明的地方加了很浓的模糊") */
|
||||
backdrop-filter: none;
|
||||
-webkit-backdrop-filter: none;
|
||||
}
|
||||
|
||||
/*
|
||||
* .glass-control —— 小控件用的"更透"档。
|
||||
*
|
||||
* 必须显式加在元素上、并且**不要同时写 bg-white**:我的 `html[data-bg='on'] .bg-white`
|
||||
* 接管规则会把任何 bg-white 拉回正文面那一档(0.88),写在这儿的透度会被它盖掉。
|
||||
*/
|
||||
html[data-bg='on'] .glass-control {
|
||||
background-color: rgb(var(--c-white) / var(--bg-glass-control));
|
||||
backdrop-filter: blur(6px) saturate(1.1);
|
||||
-webkit-backdrop-filter: blur(6px) saturate(1.1);
|
||||
}
|
||||
|
||||
html[data-bg='on'] .bg-white {
|
||||
@ -769,6 +794,62 @@ html[data-bg='on'] .hover\:bg-gray-100:hover {
|
||||
* ③ 导航栏**完全不透明**:它是框架,不该跟着壁纸一起虚化。
|
||||
* 这与内容面板要通透是**两个方向**的要求,别合并成一条规则。
|
||||
*/
|
||||
/*
|
||||
* ★ 两类面要分开处理(2026-09-14 用户第二轮批评):
|
||||
*
|
||||
* 「你把大量需要打底的场景(弹窗正文等)改为了透明。真正该透明的地方(空白区域)
|
||||
* 加了很浓的模糊」
|
||||
*
|
||||
* 也就是我上一版把两类搞反了:
|
||||
* - **承载文字的面**(正文卡、弹窗、列表、输入条):必须够实 + 轻模糊,
|
||||
* 否则字压在壁纸上读不动 —— 这是"打底",不是"玻璃";
|
||||
* - **空白/页面底**(详情区空态、面板缝隙、page 底):透明且**不模糊**,
|
||||
* 壁纸在这里应该是清晰的照片,不是一团糊。
|
||||
*
|
||||
* 规则落点:`--bg-glass` 只作用在 `.bg-white` 这一族(承载内容的那些面),
|
||||
* 而 `.bg-gray-50` / 页面底保持 transparent 且不参与模糊。
|
||||
*/
|
||||
/*
|
||||
* 浮动面板的几何 **始终生效**(圆角 + 缝隙 + 投影 + 一点朦胧),不只在壁纸模式下。
|
||||
*
|
||||
* 用户(2026-09-14):「通信页面大面积缺失圆角与玻璃效果,所有有内容与无内容区域
|
||||
* 都是硬截断」—— 根因是这些规则原先**全写在 `html[data-bg='on']` 里**:
|
||||
* 没开壁纸的账号看到的是硬边、不透明、贴在一起的面板,硬截断就是这么来的。
|
||||
*
|
||||
* 所以几何部分下沉到这里(无条件的基线),壁纸相关的加强(朝向照片的透明度、
|
||||
* 强模糊、面板间露出壁纸)仍留在下面的 data-bg 段里 —— 两者是叠加关系,不是替代。
|
||||
*/
|
||||
.app-shell {
|
||||
padding: var(--pane-gap);
|
||||
gap: var(--pane-gap);
|
||||
}
|
||||
|
||||
.app-shell > * {
|
||||
border-radius: var(--radius-card);
|
||||
overflow: hidden;
|
||||
box-shadow: 0 8px 24px rgb(15 23 42 / 0.08);
|
||||
/* 圆角处的背景不要溢出圆角外(否则边缘会出现方角残影) */
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
/* 基线朦胧:没开壁纸时也有一点玻璃感,而不是一块硬塑料 */
|
||||
.app-shell > *,
|
||||
.narrow-shell > *:not(.narrow-nav) {
|
||||
backdrop-filter: blur(var(--bg-blur-panel)) saturate(1.05);
|
||||
-webkit-backdrop-filter: blur(var(--bg-blur-panel)) saturate(1.05);
|
||||
}
|
||||
|
||||
/* 窄屏:内容面板同样浮起来(与底部导航那条悬浮玻璃一致) */
|
||||
.narrow-shell {
|
||||
padding: var(--pane-gap) var(--pane-gap) 0;
|
||||
gap: var(--pane-gap);
|
||||
}
|
||||
|
||||
.narrow-shell > *:not(.narrow-nav) {
|
||||
border-radius: var(--radius-card);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
html[data-bg='on'] .app-shell {
|
||||
padding: var(--pane-gap);
|
||||
gap: var(--pane-gap);
|
||||
@ -869,3 +950,78 @@ select,
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ═══════════════════════════════════════════════════════════════════
|
||||
* 窄屏底部导航:悬浮玻璃条
|
||||
*
|
||||
* 用户(2026-09-14):「窄屏布局的导航栏还是固定底部延伸,没有玻璃效果,也没有悬浮」。
|
||||
* 原来它是 `border-t bg-chrome-900` 的通栏 —— 贴着屏幕底边铺满宽度,与宽屏那套
|
||||
* 「浮动面板 + 留缝」的观感完全脱节(宽屏侧栏虽然不是玻璃,但内容面板是浮起来的)。
|
||||
*
|
||||
* 改成:离底边留 10px、左右各留 10px、圆角、深色半透明 + 背景模糊,落在壁纸之上。
|
||||
* 安全区(iPhone 手势条)并入下外边距,否则悬浮条会被手势条压住。
|
||||
*/
|
||||
.narrow-nav {
|
||||
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);
|
||||
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);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/*
|
||||
* 视图切换动画。
|
||||
*
|
||||
* 用户:「页面极度缺少动画,所有页面都是直接出现」。
|
||||
*
|
||||
* 做法:只在 <html> 上挂一个短命的类(由 App 的 effect 在 viewMode/页签变化时重新触发),
|
||||
* 由它给外壳的直接子面板加一次入场动画。**不改 DOM 结构** —— 面板本身是 flex 链上的
|
||||
* 一环,套一层动画 wrapper 会把 flex 传递改掉(这类改动最容易把窄屏覆盖层弄坏)。
|
||||
*/
|
||||
@keyframes pane-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(6px) scale(0.995);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
html.view-switch .app-shell > *,
|
||||
html.view-switch .narrow-shell > * {
|
||||
animation: pane-in 220ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
|
||||
}
|
||||
|
||||
/* 菜单/建议列表:轻微放大淡入,避免"啪"地出现 */
|
||||
@keyframes menu-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-4px) scale(0.985);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
html.view-switch .glass-control,
|
||||
.animate-menu-in {
|
||||
animation: menu-in 140ms ease-out both;
|
||||
}
|
||||
|
||||
/* 尊重系统设置:关了动画就一点都不动(前庭功能敏感的人会被位移动画伤到) */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
html.view-switch .app-shell > *,
|
||||
html.view-switch .narrow-shell > *,
|
||||
html.view-switch .glass-control,
|
||||
.animate-menu-in {
|
||||
animation: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user