The project shipped a black-and-white theme that was only half converted: the login page looked right, the message page was halfway, and the settings page had not been started. This finishes the move to the CYBER reference in prototype_reference/. Colors now come from a single token source (styles/variables.scss), where every semantic color is declared twice: once as OKLCH for the CSS, and once as an RGB triple so translucent variants can be built as rgba(var(--*-rgb), alpha). Cyan is the system itself, amber means the user has to intervene, green means the machine is working, and red only ever means something broke. The RGB triples are derived from the OKLCH values so the two declarations cannot drift apart. Pages adopt the .cy-* shell classes from the reference (view, panel, kpis, tabs, grid, table, field) instead of ad-hoc markup, which is what makes 19 of 26 views consistent. The remaining seven are deliberately bespoke: chat streams, the kanban board, the workflow canvas, the terminal, and the missing-agent screen. The chart palette and the kanban column colors move into single-source modules so they cannot drift either. A new guard test rejects raw hex colors, named colors, and literal RGB triples anywhere in the client source, with an explicit exemption list for the places that genuinely cannot read a CSS variable. The existing chat semantics spec keeps the chat chain honest. No behavior changes: no logic, no i18n keys, no data structures, and the /chat-run event contract is untouched.
12 KiB
UI 基线(CYBER 暗色单主题)
本文件是 hermes-ui 的视觉语言唯一依据。页面样式与本文冲突时,以本文为准;
本文没覆盖的场景,先在 docs/arco-mapping.md 补映射、再回本文补约定,然后才动代码。
- 样板页:
views/LoginView.vue(装饰位面 + 表单)、components/layout/AppSidebar.vue(导航 + 弹窗 + tag) - 令牌源:
packages/client/src/styles/variables.scss(CSS 变量 + SCSS 委托变量) - Arco 实际外观由
styles/global.scss的 Arco token bridge 决定;styles/arco-theme.ts是意图说明与测试锚点 - 组件映射:
docs/arco-mapping.md
历史:本文件曾描述「黑白水墨(Pure Ink)」三主题(ink light / ink dark / comic)。 亮度/风格切换器已移除,暗色是唯一主题,该描述不再适用。 当前主题推进状态见
docs/cyber-theme-plan.md。
1. 三色语义系统(最高优先级)
每种颜色只承担一种含义,不得混用。
| 颜色 | 令牌 | 含义 | 典型用途 |
|---|---|---|---|
| 霓虹青 | --accent-primary |
系统本体 | 品牌、主按钮、当前选中、链接 |
| 琥珀橙 | --warning |
需要你介入 | 审批、等待确认、上下文将满、中断态 |
| 荧光绿 | --success |
机器在动 | 工具成功、流式输出、连接健康 |
| 红 | --error |
出错 | 仅表示出错,不参与上面三色分工 |
- 失败时不要靠「加深强调色」表达,必须换到
--error—— 否则四个语义挤在同一色相里,紧急程度就读不出来了。 --accent-info是第四种蓝,只在需要与青/橙/绿都区分开时用(如链接性提示)。- 同一语义在全项目必须用同一个令牌。看到两个文件里「橙」是不同色值,就是 bug。
状态色的完整取值
| 令牌 | OKLCH | RGB 三元组 | 说明 |
|---|---|---|---|
--accent-primary |
oklch(0.805 0.148 188) |
0, 221, 209 |
霓虹青 |
--accent-hover |
oklch(0.870 0.150 188) |
16, 243, 230 |
悬停态 |
--accent-muted |
oklch(0.520 0.060 188) |
— | 弱化强调 |
--success |
oklch(0.860 0.190 128) |
173, 231, 78 |
荧光绿 |
--warning |
oklch(0.780 0.155 68) |
247, 162, 50 |
琥珀橙 |
--error |
oklch(0.665 0.185 22) |
240, 90, 94 |
红 |
--accent-info |
oklch(0.700 0.110 245) |
95, 165, 222 |
蓝 |
--kanban-review |
oklch(0.722 0.177 305.5) |
192, 132, 252 |
看板 review 列分类色(分类色,非语义色) |
--kanban-review是唯一的分类色令牌:看板 9 个列状态装不进三色语义系统, 按「流程阶段」维度分色。它仍然走令牌体系,所以rgba(var(--kanban-review-rgb), α)能拼出弱底色。
半透明用 RGB 三元组拼 alpha,因为 OKLCH 无法直接拆 alpha:
color: rgba(var(--accent-primary-rgb), 0.55);
box-shadow: 0 0 12px rgba(var(--success-rgb), 0.22);
每个需要拼 alpha 的令牌都有配套的 --*-rgb。要新增半透明语义色,必须同时加 RGB 三元组。
语义底与语义线
| 令牌 | 值 | 用途 |
|---|---|---|
--accent-soft |
oklch(0.805 0.148 188 / 0.13) |
强调色弱底 |
--success-soft / --success-line |
… / 0.12 / … / 0.40 |
绿色弱底 / 绿边框 |
--warning-soft / --warning-line |
… / 0.12 / … / 0.42 |
橙色弱底 / 橙边框 |
--error-soft / --error-line |
… / 0.11 / … / 0.42 |
红色弱底 / 红边框 |
2. 背景与描边
背景由深到浅四层,越靠上层越亮(向上浮):
| 角色 | 令牌 | OKLCH | 用途 |
|---|---|---|---|
| 页面底 | --bg-primary |
oklch(0.155 0.012 250) |
页面底色 |
| 次级底 | --bg-secondary |
oklch(0.130 0.012 250) |
卡片 / 面板(比页面更沉) |
| 侧栏 | --bg-sidebar |
oklch(0.118 0.013 251) |
比卡片更沉 |
| 容器 | --bg-card |
oklch(0.185 0.014 248) |
容器 / 输入区(比页面更亮) |
| 容器悬停 | --bg-card-hover |
oklch(0.225 0.016 246) |
|
| 输入底 | --bg-input |
oklch(0.105 0.012 252) |
比卡片更沉,形成凹陷感 |
| 代码底 | --code-bg |
oklch(0.115 0.014 250) |
描边发丝线分两档:--border-color(oklch(0.305 0.018 242))、--border-light(oklch(0.255 0.016 244))。
硬编码 hex 是 bug,除非是图表色板(见 §7)。
3. 文字
| 角色 | 令牌 | OKLCH | 用途 |
|---|---|---|---|
| 正文 | --text-primary |
oklch(0.945 0.006 200) |
|
| 次要 | --text-secondary |
oklch(0.860 0.008 210) |
|
| 弱化 | --text-muted |
oklch(0.705 0.014 230) |
|
| 极弱 | --text-faint |
oklch(0.520 0.014 236) |
禁用态 / 极次要信息 |
| 强调色上文字 | --text-on-accent |
oklch(0.160 0.030 200) |
深色,保证对比 |
| 浮层上文字 | --text-on-overlay |
oklch(0.945 0.006 200) |
反色场景一律用 --text-on-accent,不要硬编码白/黑。
4. 字体栈
// UI(系统中英混排)
$font-ui: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Hiragino Sans GB',
'Microsoft YaHei', 'Segoe UI', Roboto, sans-serif;
// 代码 / 命令 / 版本号
$font-code: ui-monospace, 'JetBrains Mono', 'SF Mono', Menlo, 'Cascadia Code', monospace;
// 终端(xterm 在 JS 里读这个,所以必须是 CSS 自定义属性)
--font-mono: ui-monospace, 'JetBrains Mono', 'JetBrainsMono Nerd Font',
'Nerd Font', 'SF Mono', Menlo, 'Cascadia Code', 'MesloLGS NF',
'Hack Nerd Font', monospace;
- Nerd Font 回退段不能删:默认 shell 提示符会输出私有区字形(分支、箭头、分隔符,如
U+E0A0–U+E0D4),缺了这些字形会整片显示为豆腐块。 $font-display复用$font-code—— 等宽是 CYBER 的核心排版特征。- 等宽字体只用于:代码块、命令、版本号、命令行提示、标识与数据。
5. 圆角 / 间距 / 字号阶梯
圆角($radius-*)—— 发丝线 + 小圆角,硬边而非圆润:
| token | 值 | 用途 |
|---|---|---|
$radius-sm |
6px | 按钮、输入框、小卡片、tag(与 Arco borderRadius: 6 对齐) |
$radius-md / $radius-lg |
8px | 面板、弹窗、大卡片 |
间距:4px 基数,常用档 4 / 8 / 12 / 16 / 24 / 32。组件内边距多用 12/16,区块间 24/32。
布局尺寸:
| token | 值 |
|---|---|
$sidebar-width |
240px |
$sidebar-collapsed-width |
64px |
$header-height |
60px |
$breakpoint-mobile |
768px |
字号阶梯:
| px | 用途 |
|---|---|
| 10 | 分组标签(uppercase + letter-spacing) |
| 11–12 | 辅助信息、meta、tag |
| 13 | 次要正文、列表项、错误提示 |
| 14 | 正文默认(body 基准) |
| 15 | 输入框文字($font-code 场景) |
| 16 | 小标题 |
| 26 | 登录页等展示型大标题 |
过渡:$transition-fast: 0.15s ease / $transition-normal: 0.25s ease。
6. 霓虹效果层
styles/global.scss 提供的 mixin,是 CYBER 辨识度的来源:
| mixin / 动画 | 用途 |
|---|---|
neon-tube |
霓虹灯管:主按钮、激活态边框 |
neon-sheen |
表面扫光 |
neon-pulse |
呼吸微光 |
@keyframes live-ring |
「机器在动」的唯一指示形态(单色绿,不轮播) |
@keyframes led-breathe |
状态灯呼吸(仅连通时) |
「机器在动」只长一个样
流式输出、语音播放、工具执行中、连接健康 —— 全部用 live-ring(荧光绿单色呼吸)。
不要做多色轮播:同屏内四种语义色同时在闪,等于四种颜色都不再表达含义。
这条在 P0 修 rainbow-glow 时被违反过,回归护栏在
tests/e2e/chat-cyber-semantics.spec.ts。
状态灯 .cy-led
7px 圆点 + 发光。连通=绿(呼吸),断开=红(静止)。
一个死掉的连接不该看起来还在动 —— 断开态不呼吸。
发光条用 inset box-shadow
左侧/顶部发光条用 box-shadow: inset 2px 0 0 <color>,不要用 border-left ——
border 会把内容宽度挤动 2px,列表行高对不齐。
7. 图表色板(唯一允许硬编码颜色的地方)
图表/数据可视化的分类色按数据维度取色,不走语义三色 —— 它们表达的是 「这是第几个类别」,不是「状态」。
规则:
- 同一张图内的分类色必须互相可辨(色相间隔足够)
- 图表色板集中定义在图表组件内,不散落
- 图表状态(成功/失败/警告)仍走语义令牌
- 图表色不得与语义色撞色到读者会误读为状态的程度
8. 组件使用约定
- 消息 / 对话框 / 通知:只准调
composables/useMessage|useDialog|useNotification适配层(签名冻结),不得在页面里直接 import Arco 的Message/Modal/Notification。 - Modal vs Drawer:短内容确认、纯信息展示用
a-modal(信息型弹窗:footer="false");需要表单编辑、长内容滚动的场景用a-drawer。 - 按钮:语义
type+status组合(warning 按钮 =type="primary" status="warning"); 占满宽用long;尺寸size="mini|small|medium|large";提交按钮html-type="submit", 加载态用:loading。 - 输入框:
a-input关闭了 attrs 透传,autofocus无效 —— 需要自动聚焦时ref+onMounted调focus();密码框type="password"。 - 表格空态:用
a-empty,不手写占位文案。 - loading:按钮级用
a-button :loading,区域级用a-spin :loading, 全局任务进度用useMessage().loading(...)(用完 close/destroy)。 - 表单:
a-form+a-form-item,校验规则 API 与 naive 不同,逐例适配。 - tag:
color="arcoblue"等内建色,:bordered="false"直接支持。
Arco 组件的暗色
项目不挂 ConfigProvider。Arco 的实际外观由 styles/global.scss 里的
--color-* / --arcoblue-* / --green-* / --orange-* 变量覆盖承载。
改主色时要同时改两处:global.scss 的 token bridge 和 styles/arco-theme.ts
(后者是意图说明 + 测试锚点)。
Arco 的 RGB 三元组变量不能当颜色用:
--arcoblue-6 的值是 22,93,255 而不是 #165dff。
写成 color: var(--arcoblue-6) 会被静默丢弃并回落到 Arco 默认色。
正确写法:color: rgba(var(--arcoblue-6), 1)。
9. 装饰位面的边界
装饰位面(ArkScope vendor 组件等纯视觉层)的判定标准:
不得承载信息、不得承载交互、不得影响可读性。
| 允许 | 禁止 |
|---|---|
| 登录页标题区装饰位面 | 聊天页(消息区 / 输入区 / 侧边栏) |
| Journey 图谱的背景层 | 任何表单页(Skills / Profiles / Settings / Models) |
| 首屏 loading / 空状态 | 任何表格页(Usage / Logs / Jobs / Kanban) |
| 任何点击交互密集区域 |
pointer-events: none 是硬要求,装饰层绝不能吃掉点击
(样板:LoginView.vue 的 .login-decor,外加 aria-hidden="true")。
vendor 素材边界:vendor/arkscore/ 下零图片/音视频素材,
由 tests/client/arkscope-vendor.test.ts 机械化卡住;Provenance 见
vendor/arkscore/PROVENANCE.md。
10. 四条不可破的规则
- 不引入第三个 UI 库——只允许 Arco Design Vue(+ 现有图标/工具链)。
- 消息气泡内部不用 Arco 组件(性能红线,见 Phase 006)。
- 装饰层一律
pointer-events: none,不承载信息与交互。 - 颜色只走令牌——语义色走三色系统,图表色走 §7 色板,硬编码 hex 一律视为待修。