Files
toor 5e1003ceb7
Build / build (push) Canceled after 0s
Playwright / e2e (push) Canceled after 0s
replace the monochrome theme with the CYBER neon-cyan skin
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.
2026-10-20 11:17:46 +08:00

12 KiB
Raw Permalink Blame History

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. 四条不可破的规则

  1. 不引入第三个 UI 库——只允许 Arco Design Vue(+ 现有图标/工具链)。
  2. 消息气泡内部不用 Arco 组件(性能红线,见 Phase 006)。
  3. 装饰层一律 pointer-events: none,不承载信息与交互。
  4. 颜色只走令牌——语义色走三色系统,图表色走 §7 色板,硬编码 hex 一律视为待修。