- 材质统一边光:slab / float / pill / pill-selected / seg-thumb / chrome-side 改为左上亮右下暗的 1px 边光 + 外侧暗线;新增 lens / field / chip 参数与 pg-float-modal - 主按钮:转动光谱环改为静态左上光谱高光,悬停沿边扫过一小段;次按钮同为 lens 玻璃 - Input / Textarea / SelectTrigger 挂 .field-glass,原生下拉与实体选择器同步;对话框按钮行 gap-3 - 提示条改 pg-float(状态色只在图标、展开不叠放);新增 GlassTooltip 接管 title 提示 - 触屏判断 input-modality.ts、touch / hover 自定义变体;animate-pg-pop 改 backwards;scroll-fade-end - 控制台外壳:侧栏无硬分隔线、折叠开关进标志行;顶栏去磨砂,右侧控件收进玻璃胶囊 - 登录页居中单卡 auth-card;详情头图「订阅」改回普通主按钮,删除 pill-solid;发现页海报角标改 glass-chip-media - 引入 simple-liquid-glass(liquid-surface.tsx);更新 docs/design 三份规范与 CHANGELOG Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
96 lines
8.4 KiB
Markdown
96 lines
8.4 KiB
Markdown
# 设计 token
|
|
|
|
> 迁入自 /opt/uhd_web `docs/features/`(2026-09-27),2026-10-08 与 uhd_web 同步。文中流媒体、播放器、落地页、套餐等段落是 uhd_web 的原始上下文,本项目没有这些页面,只作材质与 token 用法参考;以本目录 README 的约定为准。
|
|
|
|
样式入口是 [app.css](../../apps/web/app/app.css)。本说明定义颜色类 token 的分层、命名与使用规则,目的是让主站之外的皮肤(如动漫版)只改 token 值就能换皮,组件源码两边保持一致。材质类的说明见[界面材质](interface-materials.md)。
|
|
|
|
## 分层
|
|
|
|
| 层 | 在哪 | 谁能引用 |
|
|
|---|---|---|
|
|
| 原色 | `@theme` 里的 `--color-ink-*`、`--color-bone-*`、`--color-gold-*` 等色阶 | 只有下一层的 token 定义 |
|
|
| 语义 token | `:root`(浅色门户)、`.dark`(深色门户)、`:root:has([data-stream-shell])`(流媒体壳)三块里的 `--content-*`、`--canvas` 等 | 材质类与组件 |
|
|
| 材质 | `pg-surface` / `pg-float` / `pg-pill` 等 class 与 `--pg-*` 参数 | 组件 |
|
|
| 组件 | `app/routes`、`app/components` 里的 class | 不引用原色、不写字面量 |
|
|
|
|
主题包只覆盖语义 token 的值(以及材质参数),不改组件选择器。流媒体壳的 token 块必须放在无层的语义 token 区,放进 `@layer base` 会被 `.dark` 的无层规则盖掉。
|
|
|
|
## 词汇
|
|
|
|
| token | 含义 | 夜间值 |
|
|
|---|---|---|
|
|
| `content-strong` / `content` / `content-secondary` / `content-tertiary` / `content-muted` / `content-faint` | 文字层级,随日夜翻转 | 中性白到灰,逐档变淡 |
|
|
| `canvas` / `surface` / `surface-raised` / `surface-high` | 页面底、普通面、抬起的卡、更高一层 | 中性近黑,逐档抬亮 |
|
|
| `brand-soft` / `brand-light` / `brand` / `brand-strong` / `brand-deep` | 品牌色族。主站无彩:夜间是白、日间是墨(2026-09-26);动漫版换成它的品牌色 | 白到浅灰 |
|
|
| `success` / `warning` / `destructive`(及 `-foreground`) | 状态色,低饱和,只用于状态提示;实底上的文字用对应的 `-foreground` | 绿 / 琥珀 / 红 |
|
|
| `wash` | 半透明"洗"层的底色:hover、按压、分隔线。透明度留在调用处,写成 `bg-wash/[0.07]`、`border-wash/10`;暗底是白,亮底是黑 | 白 |
|
|
| `on-media-*`、`on-media-wash` | 压在视频 / 海报上的文字与洗层,不随日夜翻转,画面永远是暗的。播放器目录一律用这一族 | 与 content 族同值,白 |
|
|
| `scrim` | 压暗画面的遮罩底色,透明度留在调用处(`bg-scrim/60`、`from-scrim/75`) | 黑 |
|
|
|
|
`bg-wash/[0.07]` 经 Tailwind 生成 `color-mix(in oklab, var(--wash) 7%, transparent)`,与原来的 `rgba(255,255,255,0.07)` 渲染结果一致;去字面量迁移时 143 对旧类到新类在同一元素上原地换类截图,字节级一致(渐变分开两个元素比对会有 Skia 抖动带来的 ±1 噪声,不是颜色差)。
|
|
|
|
## 字号
|
|
|
|
`@theme` 里的 `--text-*` 只定字号不定行高,行为等同原来的 `text-[Npx]`;自带行高的 `text-xs` / `text-sm` 等 Tailwind 档继续用,两套不混。组件按角色引用,不写像素。
|
|
|
|
| 阶 | token | 值 |
|
|
|---|---|---|
|
|
| 正文 | `micro` / `label` / `meta` / `caption` / `body` / `control` / `lead` / `lead-lg` | 10 / 11 / 12 / 13 / 14 / 15 / 16 / 17 px |
|
|
| 标题 | `title-xs` / `title-sm` / `title` / `title-lg` / `headline-xs` / `headline-sm` / `headline` / `headline-lg` / `display-xs` / `display-sm` / `display` / `display-lg` / `display-xl` | 18 / 20 / 22 / 24 / 26 / 28 / 30 / 32 / 34 / 42 / 44 / 52 / 56 px |
|
|
| 流式 | `hero-stream(-sm/-md)`、`detail-title`、`notfound-code`、`pricing-hero`、`pricing-title`、`landing-*` | 各处 clamp 原值,按用途命名 |
|
|
|
|
2026-09-12 迁移时零散字号并入最近一档(10.5 → 11、13.5 → 14、0.72rem → 11、1.05rem → 17 等,最大偏差 0.6px,约 120 处),经页面级截图复验;标题阶逐档保留现状值,流式标题各处原值保留,收敛是设计决定另议。
|
|
|
|
tailwind-merge 不认识的 `text-*` 会被当成文字颜色,`text-control text-muted-foreground` 合并时字号会被丢掉。登记表不再手写:[gen-design-tokens.mjs](../../apps/web/scripts/gen-design-tokens.mjs) 从 app.css 抽出字号、缓动、圆角、时长 token 生成 `app/lib/design-tokens.generated.ts`,`cn()` 读它;改了 app.css 跑 `deno task gen:tokens`,`deno task ci` 校验生成物是最新的。
|
|
|
|
## 圆角
|
|
|
|
控件 `rounded-md`、输入与小按钮 `rounded-lg`、卡片 `rounded-xl`、面板 `rounded-2xl`、抽屉与大卡 `rounded-3xl`、药丸 `rounded-full`。这些是 Tailwind 名,值由 `--radius` 派生,主题改一个变量整体缩放。角色型的三个:`rounded-tight`(徽章、骨架屏等小件,原来的裸 `rounded`)、`rounded-t-drawer`(手机端底部抽屉顶角)、`rounded-slab`(门户大卡)。不写 `rounded-[..]`。
|
|
|
|
## 动效
|
|
|
|
时长四档加两档特例,缓动五种,组件只用这些名字:
|
|
|
|
| 类 | 值 | 用途 |
|
|
|---|---|---|
|
|
| `duration-micro` | 150ms | 按压、hover 这类微反馈 |
|
|
| `duration-base` | 200ms | 绝大多数颜色 / 透明度过渡 |
|
|
| `duration-layout` | 300ms | 尺寸、位置变化 |
|
|
| `duration-slow` / `duration-hero` / `duration-cinematic` | 500 / 700 / 1000ms | 入场、hero、装饰性动画 |
|
|
| `ease-standard` | cubic-bezier(0.4, 0, 0.2, 1) | 默认 |
|
|
| `ease-spring` / `ease-spring-soft` | 回弹 | 滑块、按压 |
|
|
| `ease-sheet` | 抽屉 | 底部抽屉进出 |
|
|
| `ease-pop` | 弹层出现 | pg-pop |
|
|
|
|
`duration-*` 是 `@utility`,写法与内置的 `duration-N` 一致(同时设 `--tw-duration`,tw-animate 的 `animate-in` 也读它)。app.css 里材质与关键帧动画的时长是逐个校准过的值,不套四档;缓动已统一引用 `--ease-*`。
|
|
|
|
## 材质参数与播放器白天模式
|
|
|
|
所有材质(播放器的 surface / pill,按钮的 pill-primary / pill-secondary / pill-selected,分段滑块 seg-thumb,门户的 slab / chrome / float,小控件玻璃 lens,输入框 field,小玻璃圆片 chip)都是"固定配方 + `--mat-<材质>-<部位>` 参数",class 只引用参数,壳与主题只覆盖参数;结构见[界面材质](interface-materials.md)。
|
|
|
|
播放器整体压在画面上,默认只有夜间,但白天模式已经留出位置:主题在播放页作用域(`:root:has([data-stream-shell="play"])`)覆盖两组东西即可,不需要改播放器组件。
|
|
|
|
- `on-media-*` 与 `on-media-wash`:控件文字与洗层。做浅色玻璃控件时改成深色文字 + 黑色洗层。
|
|
- `--mat-surface-*` / `--mat-pill-*`:材质参数。做浅色玻璃或平面 pop 材质时换底色与线色,blur 设 none 就是平面。
|
|
|
|
视频面本身永远是黑的,不在主题范围内。
|
|
|
|
## 规则
|
|
|
|
- 组件里不出现 `bone` / `ink` / `gold` 原色类、`white` / `black` 透明度写法和类名里的十六进制颜色。流媒体与播放器连 JS 里的十六进制也不写;测速图表、二维码库这类只接受颜色值的地方用组件内常量表。
|
|
- 组件里不出现 Tailwind 调色板颜色(`emerald-*`、`amber-*`、`rose-*`、`blue-*` 等):状态用 `success` / `warning` / `destructive`,装饰性图标与强调用 `foreground` 的透明度。
|
|
- 组件里不出现 `text-[Npx]` / `text-[Nrem]` / `text-[clamp(...)]`,字号只从阶梯取。
|
|
- 组件里不出现 `duration-N`、`ease-[...]`、裸 `rounded`、`rounded-[...]`。
|
|
- 改了 app.css 里的 token 就跑 `deno task gen:tokens`,让 tailwind-merge 的登记表跟上;CI 会校验。
|
|
- 播放器(`app/routes/stream/player/`)里压在画面上的东西用 `on-media` 族;流媒体浏览页用 `content` / `wash` 族。分不清就问一句:主题切到浅色时它应不应该变色。
|
|
- 新的语义需求先加 token 再用,不在组件里临时拼色。
|
|
- 按钮 hover 不填实心 `primary` / `foreground`;浮层不手写 `shadow-2xl`,用 `pg-float`。
|
|
- `scripts/check-design-tokens.sh` 在 `deno task ci` 里对整个 `app/` 做守卫(落地页组件与 `/dev/ui` 除外)。确实需要例外时(二维码必须白底、支付品牌色),在该行或上一行写注释 `token-allow: 原因`,不另开白名单。
|
|
|
|
## 迁移状态
|
|
|
|
- 已迁移:颜色、字号、圆角、时长与缓动全部 `app/`(2026-09-27 守卫扩到全站)。
|
|
- 未迁移:落地页组件(`app/components/landing`)仍固定夜间、有装饰性字面量,落地页日间另做;测速页图表配色是组件内的常量表(已改无彩)。
|
|
- 材质已全部参数化;`pg-beam`、`tab-slider`(滑块的位移动效,外观是 `seg-thumb`)、`spd-bg` 这类效果不算材质。
|
|
- 三个本来就不存在于色阶里的类(`text-bone-600`、`text-gold-50`、`to-gold-600`)在迁移时删除,它们原本不产生任何样式。
|