# dsh-freestyle-theme · 视觉规范(v0.4) 本文是实现依据:代码里的常量必须能在这里找到出处,这里的数字不能在代码里失真。 --- ## 1. 色彩模型 一套主题 = **四个色彩轴 + 两个外观轴**。 | 轴 | 字段 | 说明 | |---|---|---| | 品牌 | `th` `c1` `l1` | 强调色相 / 彩度 / 明度 | | 中性 | `neutralTint` | 灰阶继承多少品牌色相,0–1,映射到彩度 `0–0.012` | | 明度骨架 | `bg` `spread` | 背景明度 + 层级对比强度(0.04–0.20) | | 状态簇 | `stateBoost` | 成功/警告/错误的彩度倍数 0.7–1.3 | | 排版 | `fontPair` `fontScale` | 字体配对与字号缩放(**预览与导出**,不注入宿主) | | 形状 | `radius` `shadow` | 3 档圆角、3 档阴影(**预览与导出**,不注入宿主) | ### 1.1 彩度封顶(硬约束) 用户拉滑杆不能突破角色上限,否则界面会"塑料化": | 角色 | 上限 | 说明 | |---|---|---| | 表面 surface | `0.030` | 背景、卡片、气泡、代码块 | | 中性 chrome | `0.012` | 滚动条、分隔线、状态点 | | 边框 border | `0.020` | 发丝线(由中性色相 + 极小彩度着色,不用纯黑/纯白) | | 文字 text | `0.030` | 任何前景色 | | 状态 state | `0.160` | success / warn / error | 品牌色 `c1` 不受封顶(它是主题的表达),但 UI 滑杆限制在 `0–0.37`。 ### 1.2 派生规则 - **中性不纯**:所有灰阶带 `neutralTint × 0.012` 的彩度,色相 = 面板色相 `ths`。这是"高级感"的主要来源。 - **边框着色**:`border-*` 用 `oklch(0.42 / 0.86, min(nC×1.8, 0.02), ths, alpha)`,不再是 `rgba(0,0,0,α)`。 - **明度骨架**:4 点 elevation(base / layer-1 / layer-2 / layer-3 / overlay)按 `spread`(0.04–0.2,预设 0.09–0.16)拉伸;浅色模式卡片保持纯白,暗色模式逐级加亮,暗色预设普遍取更大的 `spread`。 - **暗色不是反相**:色相保持、彩度 −10%、明度 +0.06。 - **文字阶梯**:浅色 `tx → +0.22 → +0.38 → +0.47`,暗色 `tx → −0.12 → −0.18 → −0.24`。每级都有对比度下限(见 §3)。 ### 1.3 令牌覆盖面 `119` 个:`107 × --dsw-alias-*`、`11 × --dsw-specific-*`、`1 × --dsw-menu-surface-fill`,明暗各一套。 `--dsw-static-*`、`--dsw-mask-blur`、`--dsw-menu-backdrop-filter` 属于结构,不改。 --- ## 2. 版面(Studio) ``` ┌──────────────────────────────────────────────────────────────┐ │ 顶栏 56 主题名 · 明暗开关 · 撤销/重做 · 分享 · 应用 │ ├────────┬───────────────────────────────────┬─────────────────┤ │ 左轨 │ 画布 │ 检查器 320 │ │ 72→240 │ 点阵底纹 + 应用预览窗 + 对比滑杆 │ 颜色/排版/形状/ │ │ 主题库 │ 缩放 50–150%,⌘+/⌘− │ 对比度(可折叠) │ └────────┴───────────────────────────────────┴─────────────────┘ ``` - **栅格**:4px 基准、8px 节奏。栅格外的尺寸只允许 1px 发丝线。 - **字阶**:11(辅助)/12(标签)/13(正文小)/15(正文)/20(分区标题);数字一律 `font-variant-numeric: tabular-nums`。 - **圆角**:控件 8、卡片 12、面板 16(跟随 `radius` 档位缩放)。 - **阴影**:三档 `shadow` 预设 —— 无 / `0 1px 1px`+`0 1px 2px` / `0 1px 2px`+`0 2px 6px`+`0 8px 24px`(第三档只用于浮层)。 - **材质**:面板底 `--dsw-alias-bg-overlay` + `backdrop-filter: blur(12px) saturate(140%)`(弹窗 8px、命令面板 2px);不加噪点纹理。 - **对比滑杆**:可拖拽分割线,左当前右候选;键盘 ←/→ 步进 2%,Shift ×5。 - **Inspect**:悬停画布元素 → 该元素 `data-token` 指定的令牌高亮 + 标注气泡(只读,不改变编辑状态;检查器里按令牌名查找)。 --- ## 3. 对比度(硬门槛) 两套并存:WCAG 2.2(合规)与 APCA(观感)。 | 用途 | WCAG 比 | APCA Lc | |---|---|---| | 正文 primary | ≥ 7.0 | ≥ 75 | | 次要 secondary | ≥ 4.5 | ≥ 60 | | 三级 tertiary / caption | ≥ 3.0 | ≥ 45 | | 非文本 UI(边框、图标,及预留的大字档) | ≥ 3.0 | ≥ 30 | 判定 **21 组**关键配对:主/次/三级文字 × base、layer-1、overlay;按钮文字 vs 按钮底;链接 vs base;tooltip 文字 vs tooltip 底;toast 文字 vs toast 底;错误 toast 文字 vs toast 底;成功/警告/错误文字 vs base;diff 标记 vs diff 底;菜单项 vs 菜单底。 配对里的语义等级由配对本身决定:`tertiary`/`caption` 用 `label-secondary` 色值(明度 `i2`),保证与 3.0 门槛有实实在在的余量,而不是靠阈值放水。 **一键修复**:保持 `h` 与 `c`,只在 `l` 上以 0.012 步长走向目标;优先动前景(`tx`),不够再动背景(`bg`),最后才动状态簇并明确提示"已尽力"。卡在合法区间端点的旋钮会被跳过,避免空转。 **发布闸门**:`pnpm check:tokens` 跑 12 预设 × 2 模式 × 21 对,正文类 ≥ 4.5、其它 ≥ 3.0,并打印最薄的一对。 --- ## 4. 动效刻度 | 场景 | 时长 | 缓动 | |---|---|---| | 按压 / hover 反馈 | 120ms | `cubic-bezier(.2,0,0,1)` | | 小元素进场(chip、toast) | 180ms | 同上 | | 面板 / 抽屉 | 240ms | 同上 | | 全屏 Studio 进出 | 320ms | 同上 | | 退场 | ≤160ms | `cubic-bezier(.4,0,1,1)` | | 控件回弹(开关、滑杆拇指) | 240ms | `linear()` 弹簧近似 | **编排**:列表不做入场错峰(只做行斑马纹,避免长库抖动);弹层用 240ms `ft-pop`(淡入 + 6px 上浮 + 0.985 缩放),退场 180ms 后卸载。 **因果动效**(唯一允许的"多余"动效,因为它解释变化来源): - 改色相 → 画布 180ms 插值过渡; - 应用主题 → 从被点色卡出发的 400ms 径向擦除。 **禁止**:首屏动画;动 layout 属性;大面(>30% 视口)回弹;`prefers-reduced-motion` 下保留任何位移动画。 --- ## 5. 交互清单 | 交互 | 触发 | 行为 | |---|---|---| | 撤销 / 重做 | `⌘Z` / `⌘⇧Z` | 50 步历史,含拖拽中间态合并 | | 命令面板 | `⌘K` | 仅 Studio 聚焦时接管,避免与壳冲突 | | 数值拖拽 | 数字标签左右拖 | 1px = 1 单位,`Shift` ×10,松手吸附 | | 缩放 | `⌘+` / `⌘−` / `⌘0` | 50–150%,0 = 100% | | 对比滑杆 | 拖拽分割线 | 双向吸附,键盘 ←/→ | | 关闭 | `Esc` | 先关命令面板 → 再关 Studio,有未应用改动时二次确认 | | 焦点 | `Tab` | 焦点陷阱在 Studio 内,关闭后归还触发器 | --- ## 6. 验收标准 1. 30 秒内能做出一个"敢截图发出去"的主题。 2. 一次令牌提交 < 16ms(119 令牌 × 2 模式),对比滑杆拖拽 60fps。 3. 21 组配对全部达标或明确标注"已尽力"。 4. 中英文字案 100% 对齐(`locale.ts` 的 key 集合一致)。 5. 不写死任何前景色:文字只用 `--dsw-alias-*`,写死仅限 `var()` 兜底。 ## 中国传统色 轨道第三项提供 32 种传统色(`TRADITIONAL`,`src/client/palette.ts`)。它们不是独立主题,而是 **品牌轴的快捷输入**:取该色的 OKLCH 色相与彩度写入 `th` / `c1`,副色按当前配色关系偏移, 中性带同色相微量彩度,明度骨架(`bg` / `spread`)保持当前模式。因此换传统色相当于换整套坐标系, 而不是只换按钮颜色;21 对对比度按新坐标系重新校验,不达标的仍可一键修复。