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 一律视为待修。