Files
UHD_Media_Tool/docs/design/interface-materials.md
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

14 KiB
Raw Permalink Blame History

界面材质

迁入自 /opt/uhd_web docs/features/(2026-09-27),2026-10-08 与 uhd_web 同步(液态玻璃、边光、输入框、提示条、触屏判断)。文中流媒体、播放器、落地页、套餐等段落是 uhd_web 的原始上下文,本项目没有这些页面,只作材质与 token 用法参考;以本目录 README 的约定为准。

样式入口是 app.css,具体色值与透明度只在 CSS 中维护。颜色 token 见设计 token,按钮与控件的用法见控件使用标准,三块壳下的实物陈列在开发态 /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 在 deno task ci 中守住(见设计 token)。

结构

一个材质 = 一份固定配方 + 一组参数。配方写在 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 把原生提示换成 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(封装 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 的触发条件和项目适配见前端规范。