Files
UHD_Media_Tool/docs/design/interface-materials.md
T
rootandClaude Opus 5.5 c9b4ceb301 fix(web): 控制台界面细节与 uhd_web 控件规范对齐
- 顶栏搜索移进右侧玻璃胶囊;输入框改淡玻璃(边线 0.46 → 0.16,悬停加深,聚焦 / 出错保留光晕)
- 新增 SegmentedControl(滑动 seg-thumb),替换站点、下载、订阅、文件、智能体列表及对话框里的实心选中块;Tabs 改为同一枚滑块
- 开关型按钮统一 outline + aria-pressed 选中外观;页头 / 工具栏次操作描边、图标钮描边圆;文件排序改 Select;下载总速度加标签
- 分页一页放得下时只留总数、空列表不渲染、按容器宽度收起按钮
- 运行状态存储区重排;智能体列表页与会话页共用外壳路由,标题与左栏不再重挂载
- 站点卡片「⋯」不再单独换行;设置导航、状态计数、多选条件改玻璃选中态

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
2026-10-08 12:02:48 +08:00

132 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 界面材质
> 迁入自 /opt/uhd_web `docs/features/`(2026-09-27),2026-10-08 与 uhd_web 同步(液态玻璃、边光、输入框、提示条、触屏判断)。文中流媒体、播放器、落地页、套餐等段落是 uhd_web 的原始上下文,本项目没有这些页面,只作材质与 token 用法参考;以本目录 README 的约定为准。
样式入口是 [app.css](../../apps/web/app/app.css),具体色值与透明度只在 CSS 中维护。颜色 token 见[设计 token](design-tokens.md),按钮与控件的用法见[控件使用标准](ui-controls.md),三块壳下的实物陈列在开发态 `/dev/ui`。
## 设计原则
全站(用户中心、公共页、测速、流媒体)是同一套审美,改样式先对照这几条:
1. **主色无彩**。夜间是白、日间是墨。彩色只来自内容(海报、剧照),外加一种很淡的棱镜光。状态色 `success` / `warning` / `destructive` 只表示状态,不做装饰。支付方式保留品牌色。
2. **棱镜光只出现在三处**:左上角的漏光 `PrismLeak`、主操作按钮左上棱边的光谱高光、流媒体入口(侧栏的播放键 `prism-ring` 与菜单里的三角 `prism-icon`)。不再往别处加彩虹。
3. **材质按层级只有三种**:
- 贴边的用 `pg-surface` / `pg-chrome`;
- 内容卡用 `pg-slab`,是磨砂面,好读优先;
- 悬浮层用 `pg-float`,只有它用较深的投影。
压在大图、海报、视频上的控件与悬浮层另用液态玻璃(见下文),只有它们做边缘折射;玻璃里的子元素只用平涂,不再叠玻璃。
4. **一个角色一种外观**:
- 主操作是玻璃胶囊加左上棱边的光谱高光,一屏只放一个;
- 次操作是描边胶囊;
- 选中态是静态的 `pill-selected`;
- 分段控件的滑块是 `seg-thumb`。
全站没有实心按钮,也没有实心的选中块。
5. **日夜两套,画面跟随页面**。大图、横向滚动行两侧的渐隐和压暗层都取页面底色,不硬切成黑色。播放页永远是夜间,落地页暂时固定夜间。
6. **同一种信息用同一种结构**:
- 套餐卡的零件在公共定价页和订阅服务页共用;
- 电影和剧集详情页共用 `DetailExtras`;
- 流媒体页面的内容区统一用 `max-w-[1800px]` 加 `px-4 sm:px-6 lg:px-10`,标题、海报行和顶栏对齐。
7. **动效只做一次性的**。入场、按压回弹、悬停反馈可以做;持续运动的装饰不做。主按钮的光谱高光静止,悬停时沿边扫过一小段。
这些规则里能机器检查的,由 [check-design-tokens.sh](../../apps/web/scripts/check-design-tokens.sh) 在 `deno task ci` 中守住(见[设计 token](design-tokens.md#规则))。
## 结构
一个材质 = 一份固定配方 + 一组参数。配方写在 class 里(哪几层、怎么叠),参数是 `:root` 上的 `--mat-<材质>-<部位>`:
| 部位 | 含义 |
|---|---|
| `bg` / `rgb` | 底色(surface 用 rgb 三元组配 `--pg-surface-alpha`,其余是完整颜色或整段 background 值) |
| `sheen` / `reflection` / `glow` | 顶部光泽、斜向反光带、鼠标辉光,整段渐变 |
| `blur` | backdrop-filter 值 |
| `border` / `hairline` | 边 |
| `highlight` / `shade` | 上沿内高光、下沿内暗线 |
| `shadow` | 外投影(配方里各层形状不同的材质,这一项存整条 box-shadow 列表) |
| `solid` | blur 不可用或需要不透明时的实心兜底 |
材质分三组:
- 播放器与媒体区:`surface`、`pill`;
- 门户:`slab`、`chrome`、`float`,以及按钮用的 `pill-primary` / `pill-secondary` / `pill-selected`、分段滑块 `seg-thumb`、小控件玻璃 `lens`、输入框 `field`、小玻璃圆片 `chip`。
浅色门户、深色门户与流媒体的差别都只是参数覆盖,不各自重写声明。换皮做平面材质时,把 blur 设成 none、光泽设成透明、投影收掉即可,class 不动。
| 场景 | 样式 |
|---|---|
| 贴边的 header、筛选栏、播放器底栏 | `pg-surface`,模糊与底色,不叠加悬浮面板的泛光亮线 |
| 悬浮层:下拉菜单、弹出框、下拉选择、对话框、抽屉、错误卡、提示条、图表提示 | `pg-float`,全站唯一。菜单类 `rounded-2xl`,对话框 `rounded-3xl`,调用处不改底色、边框、投影。对话框、确认框、抽屉再加 `pg-float-modal`(底取 `--mat-float-modal-bg`,由 `Dialog` / `AlertDialog` / `Sheet` 挂上)。菜单里再弹出的子菜单、手机底部抽屉加 `pg-float-solid`(不透明),避免透出下面一层。本项目的 `pg-float` 底是不透明的 popover 实底、不做背景模糊(SEARCH-4,2026-09-30:半透明弹层压在资源列表上看不清),立体感只靠边光与投影 |
| 药丸 HUD、徽章等小型悬浮元素 | `pg-pill` |
| 悬停提示 | 照旧写 `title`,根组件里的 [GlassTooltip](../../apps/web/app/components/glass-tooltip.tsx) 把原生提示换成 `pg-float` 气泡;元素在液态玻璃里时,气泡以那块玻璃的边为准,不压在玻璃上 |
新组件先确认它是贴边、内容还是悬浮,再复用对应样式。滚动行卡片本体和高频跟随鼠标的进度气泡不加背景模糊。
## 门户材质
`pg-slab` 用于外层内容卡,`pg-chrome` 用于侧栏、顶栏和贴边操作条,`pg-float` 用于悬浮面板;嵌套的子卡保持轻填充,避免多重玻璃。Dialog / Card 原语自带的 utilities 可能覆盖 components 层的材质类,要核对最终的 class 合并和层叠,不要继续叠加透明度补丁。
内容卡是磨砂面,不追求透明:背景模糊只让底下的明暗和淡彩柔和地渗进来,层次靠亮棱边、顶部内高光和轻投影区分。投影只用贴边一层加很淡的环境一层,日间更轻(`--shadow-card` 按日夜分别给值)。页面底层是 `bg-page-glow` 的无彩明暗光斑,不铺网格。`PrismLeak` 在每个页面外壳各放一个(落地页与播放页除外),浓度与叠加方式见 `--mat-leak-*`。
主操作 `pill-primary`:
- 光从左上照来:左上棱边是一段光谱高光,右下是一段更淡的回光,内侧透一层很淡的同色光;本体与次按钮同为 lens 玻璃;
- 静止不转,悬停时变亮并沿边扫过一小段,减少动态效果时只变亮;
- 参数是 `--mat-lens-*`(本体)与 `--prism-*`(高光)。
次操作 `pill-secondary` 是 lens 玻璃(`--mat-lens-*`),选中态 `pill-selected` 比它多一层填充(`--mat-pill-selected-*`)。按下回弹 `scale(0.96~0.97)`。
动效:
- 页面入场用 `motion-safe:animate-blur-in`(失焦到清晰,填充模式 backwards,播完不留 filter,避免破坏 fixed 定位的子元素)。
- 需要鼠标反馈的卡片(套餐卡)挂 `.pg-spotlight`,并用 `rippleMove` 写入 `--mx/--my`。光在卡面底色之上、文字之下,亮度参数是 `--mat-spotlight`,只在能悬停的设备上出现。
- `.pg-beam` 巡边光只留给少数常驻小徽标。
## 液态玻璃
压在大图、海报、视频上的控件用液态玻璃:边缘一圈把背后的画面弯折放大,中间不变形。组件是 [liquid-surface.tsx](../../apps/web/app/components/liquid-surface.tsx)(封装 `simple-liquid-glass`),按尺寸分三档:
- `lens`:小控件。按钮本身的材质参数是 `--mat-lens-*`(几乎透明的填充、左上亮右下暗的内阴影边光、外侧 1px 暗线);压在大图上的主按钮和图标键外面再套 `LiquidLens` 加真折射,按钮挂 `.btn-liquid` 去掉自己的底。主按钮的折射边缘带少量色散;尺寸会动画变化、不适合套折射的自定义控件用 `.lens-glass`;
- `regular`:栏与胶囊。控制台顶栏右侧的胶囊(通知、智能体、日夜切换、账户)用它的只模糊档(`noRefraction`);
- `frost`:字多的悬浮面板,只做真模糊(24px)加一层底色,不折射:以可读为先。
全站其余玻璃不折射,但用同一套边光语言:左上亮、右下暗的 1px 内阴影边光,加外侧 1px 暗线。包括内容卡 `pg-slab`、悬浮层 `pg-float`(提示条也走它:状态色只在图标上,不开 `richColors`;展开排列不叠放)、选中态 `pill-selected`、分段滑块 `seg-thumb`、药丸 `pg-pill`。激活态(菜单展开)在玻璃里多一层淡填充,不改描边。压在图片上的小控件(海报角标、状态圆片)统一用烟色小玻璃 `glass-chip-media`,白字,状态色只留在圆点上(`StatusBadge onMedia`);页面底上的同类圆片用 `glass-chip`,参数是 `--mat-chip-glass`。贴边的 `pg-surface` / `pg-chrome` 不加边光。
折射只有 Chromium 桌面可见,其他浏览器与触屏设备由组件退回磨砂。背后没有画面的地方(内容卡、表单)不用液态玻璃,折射看不出来。玻璃之间至少留 8px,不叠放。含玻璃的弹层外壳不能挂一直生效的透明度动画(`animate-pg-pop` 用 `backwards`):Chromium 会把它当成背景根,里面的模糊采样不到页面。
本项目里压在画面上的只有作品详情头图(见下文)和发现页海报的角标;头图的操作按钮坐在近乎不透明的底色渐变上,不在剧照像素上,所以用普通按钮、不套 `LiquidLens`。
## 流媒体大图
流媒体首页与详情页的大图通栏显示,跟随日夜:
- 压暗层(`.hero-vignette` 与各层渐变)取页面底色:夜间压暗配浅色字,日间提亮配深色字。
- 整个画面层在下沿渐隐成透明,露出页面的底色与光斑,和下面的内容连成一片。
- 渐隐加在不缩放的外层,ken-burns 放大时不会裁出硬边。
详情页的标题区向上压进渐隐区,海报、规格徽章和按钮在首屏内。
画面层下面垫一层页面底色,加载占位 `BackdropSkeleton` 用同一个盒子、同样的渐隐。这样图片没到、数据没到的时候,顶栏下面也不会先露出后面的棱镜漏光再被盖掉,切换首页和详情页时顶栏颜色不跳。
列表页(电影、剧集、收藏、合集、演职人员)不做色带:标题、筛选条和内容坐在同一张页面底上。筛选条 `StickyFilterBar` 平时透明。桌面吸顶,吸住后磨砂底向上延伸盖住顶栏区域(顶栏本身不铺底),顶栏胶囊浮在这块磨砂上。手机不吸顶,随正文滚走,滚过后由顶栏 Logo 右侧的筛选胶囊 `HeaderFilterCapsule` 接替,点开选分类和排序;不做常驻吸顶,也不做上滑弹出,底部栏不再加入口。
## 控制台作品详情头图
媒体库作品页与发现页 TMDB 详情共用 `MediaHero`(2026-10-07 方案 A):
- 剧照铺在内容区顶部(左右伸到内容区的内边距,向上伸到返回链接后面),`.media-hero-backdrop` 让剧照上下和右缘渐隐成透明,露出页面底色与光斑,不做圆角卡片;
- 剧照上压一层页面底色的渐变(`--mat-hero-scrim-side`):左侧文字区近乎不透明、右侧露出剧照;窄屏海报与文字上下排,改为自上而下压底色(`--mat-hero-scrim-stack`);
- 文字用常规前景色 token,日夜同一结构,只是 `--background` 不同;没有背景图时不渲染剧照层,就是普通头部;
- 播出状态与作品状态 / Emby 徽标在同一行;操作按钮在外链行下方,「订阅」是唯一的主操作(普通 `pill-primary`),其余是次操作。2026-10-07 曾因转动的光谱环在剧照上看不清改用主色实心 `pill-solid`;静态的左上光谱高光在剧照上看得清,2026-10-08 起取消这个例外。
## 其他
- 侧栏的选中项由滑块(`seg-thumb`)承担主要形态,导航文字与 hover 保持清晰;分组展开、滚动和路由变化都会影响滑块位置。
- 控制台侧栏贴边,不做浮起卡片;右边不画硬分隔线,由 `pg-chrome-side` 给内侧细亮边、外侧细暗线和淡投影。分组小标题(概览、获取、整理、系统)保留:它们和菜单项不同名,是导航的分区。折叠开关在标志行:展开时在名称右侧,收起后标志悬停变为展开图标。
- 控制台顶栏与登录页顶栏不铺磨砂(磨砂栏会成为背景根,里面的玻璃糊不到页面),用页面底色渐隐托住标题;控制台右侧搜索、通知、智能体、日夜切换与账户收进一枚玻璃胶囊,胶囊里的按钮是平的(`bare`),搜索入口是胶囊里的一格平涂淡底,不套 `.field-glass`;登录页右侧只有日夜切换一颗,不套胶囊。
- 登录页只留标题(初始化和二次验证保留一句操作说明),整页居中一张卡,桌面与手机同一套;卡片是 `pg-slab auth-card`(底换成实在的磨砂 `--mat-auth-card-bg`,卡片、输入框、页面三层分得开)。
- 输入框、多行输入与下拉选择的触发器统一用 `.field-glass`(淡底 + 1px 实边,悬停时边线加深一档,聚焦 / 展开时外线加深并带淡光晕,出错时红线加淡红光晕;参数 `--mat-field-*`)。本项目 2026-10-08 把日间边线从 0.46 调到 0.16、底换成半透明白(夜间边线 0.36 → 0.16):控制台的筛选条和搜索框很密,0.46 的边读成一圈黑框;靠聚焦与出错状态保证可辨认,与 uhd_web 的参数在这一处不同,由 `Input` / `Textarea` / `SelectTrigger` 挂上;原生 `<select>` 与长得像下拉的按钮也挂它。调用处只给尺寸和内边距,不再各写底色、边框、阴影。
- 改支付界面的样式时,要覆盖确认、二维码、错误与返回路径。套餐的优惠金额从价格推导,不写死。交易摘要用现有的 RemarkText 展示,不为排版改写后端摘要的含义。
主动使用 Taste 的触发条件和项目适配见前端规范。