Files
Agent-System-Dev/DESIGN.md
T
weichen 8af945a1d5 Make development gates preserve work and verifiable evidence
Why: cleanup, component synchronization, receipt recording and credential handling could contradict the documented development boundaries.

Evidence: SELF 75 isolated governance tests and source checks are captured in .task/feature-governance-reliability.md; combination and CI verification follow.

Impact: hardens local task and CI tooling, aligns policy and component documentation, and adds continuous regression tests without changing product behavior.

Refs: .task/feature-governance-reliability.md; policy/governance.md; policy/platform-admission.md
2026-10-05 12:36:02 +00:00

18 KiB
Raw Blame History

Agent-System-Dev 设计系统(DESIGN.md)

写给 Agent 与人:在本仓生成或修改任何 UI 之前,先遵循本文,再发明新的视觉规则。 违反本文视为设计系统缺陷,不是风格偏好。

四原则:美观、现代、简洁、易用。每条规则都是四原则在某一维度上的可执行化。

参照体系:ZCode(zai-org/ZCode)开源仓的 DESIGN.md、packages/ui/src/styles.css 主题真值与动效配方。本文的色板、字号标尺、圆角层级、动效参数均逐条对照其源码校准。


1. 产品性格

Agent-System-Dev 是桌面优先、Web 兼容的 AI 工作台。界面应冷静、高密度、可操作,而非装饰性的。

为长会话、高信息密度、可读的对话与工具输出、键盘驱动的工作流而设计。

避免:营销式大留白、默认渐变装饰、大面积品牌色铺底、背景/卡片/浮层层次含混。

2. 主题

  • 用户可选主题:跟随系统 / 浅色 / 深色。实现为 :root[data-theme='dark' | 'light']。
  • 深色基准为 Zai Dark 复刻;浅色基准为 Zai Light。令牌唯一来源:@ui/tokens.css。
  • 禁止在组件里出现裸色值(hex/rgb 字面量);一切颜色经语义令牌消费。 守护测试(design-guard.test.ts)以基线棘轮拦截新增裸值。

2.1 表面阶梯(层次靠背景阶梯,不是描边堆叠)

令牌 深色 (Zai Dark) 浅色 (Zai Light) 用途
--bg-inset #101010 #ececee 窗口间隙(面板化布局的"底座")、代码底
--bg #161616 #f8f8f8 应用底、主区背景
--bg-panel #202020 #ffffff 侧栏/面板/头部
--bg-raised #2b2b2b #ffffff 卡片、输入、菜单、浮层
--bg-hover rgba(255,255,255,.05) rgba(13,13,13,.05) 通用悬停
--bg-active rgba(255,255,255,.10) rgba(13,13,13,.08) 选中态

2.2 边框(发丝三档)

--border-soft: rgba(255,255,255,.06) / --border: rgba(255,255,255,.10) / --border-strong: rgba(255,255,255,.15)(浅色对应 13,13,13 的 .08/.10/.16)。 边框只做轮廓;选中优先用 --bg-active 填充而非换边框色。

2.3 文本

--text(主读文本,深 #d4d4d4 / 浅 #262626 / 墨绿 #082d4f)。 --text-dim:深 66% / 浅 68% / 墨绿 70%。 --text-faint:深 52% / 浅与墨绿 58%。 用文本层级制造信息密度,先于增加更多边框或颜色。

门槛(contrast-guard.test.ts,WCAG 2.1):

  • --text 与 --text-dim 在主区表面(--bg、--bg-panel、--bg-raised、代码底 --bg-inset)不低于 4.5:1。
  • --text-faint 不低于 3:1,并且只用于装饰:占位符、chevron、kbd、关闭图标的默认色。
  • 承载决策或需要读完的文字从 --text-dim 起步:表头、确认详情、工具清单、空态说明、设置项描述、状态词。不要把 faint 当内容色。

侧栏另用 --text-sidebar-dim(墨绿 78%)与 --text-sidebar-faint(墨绿 62%),门槛与主区相同,只跟 --bg-sidebar 对拍。 侧栏会把 --text* 重映射成侧栏色。挂在侧栏 DOM 里、但画在主区纸面上的浮层(账户菜单)改用 --text-workspace*,这是同一套文字的不被重映射的副本。

2.4 强调与语义色

  • 交互强调蓝:--accent(深 #4099ff / 浅 #0b7fff)。只用于链接、选中指示、聚焦环、 进行中指示;不做大面积铺底、不做主按钮底色。

  • 主按钮:单色系反色——--primary(深 #ffffff / 浅 #0d0d0d)配 --primary-foreground (反向黑/白)。品牌色保持克制。

  • 语义图形色:--ok #46bf72、--warn #ff8a30、--err #ff5c5c(浅色与墨绿 #1e8a3e / #d17300 / #e03131)。 语义色只表语义。图形色(状态点、描边、色条)在 --bg / --bg-panel / --bg-raised 上不低于 3:1。 图形色不作文字。 链接、状态词、差异文字、空闲状态字用下面的文字档。

  • 文字档(同一色相,专门保证 4.5:1,含铺在 *-soft 上):

    令牌 深色 浅色 / 墨绿 用途
    --accent-text #58a6ff #0858b0 链接、动作字
    --warn-text #ff8a30 #8d4d00 警告文字;也作警告徽标底
    --err-text #ff7272 #a92525 错误文字;也作错误徽标底
    --ok-text #46bf72 #17682f 成功状态字
    --idle-text #929292 #636363 空闲状态字
    --diff-add-text #7dcea0 #17682f 差异增加的文字
    --diff-remove-text #ff9b9b #a92525 差异删除的文字

    徽标:底用对应 *-text,字用 --text-on-semantic(深 #101010 / 浅与墨绿 #ffffff)。

  • 等你确认用 --wait(深 #8b93ff / 浅 #3a46c8 / 墨绿 #3d5a9a)和 --wait-soft。 不借用成功绿,也不用红或橙装饰等待。

  • 差异视图:增加用 --diff-add / --diff-add-text,删除用 --diff-remove / --diff-remove-text。

  • 空闲任务的图形用 --task-idle,文字用 --idle-text。定时任务用 --task-scheduled。两者不要混成同一种灰。

2.5 墨绿主题(可选,data-theme='molv')

暖纸白工作区、深海军蓝左栏与顶栏、翠绿强调。只覆盖表面与语义色;字号标尺、圆角、间距沿用 §3–§5,不另起一套。左栏与顶栏消费 --bg-sidebar / --text-sidebar*(深色与浅色下别名到面板与正文,墨绿下翻成海军蓝)。

令牌 墨绿 用途
--bg-inset #e0e0db 窗口间隙
--bg #f2f2f0 对话主区
--bg-panel #fbfbfa 右栏等面板
--bg-sidebar #082d4f 左栏、顶栏
--text #082d4f 主读文本
--text-sidebar #e9f0f6 左栏与顶栏文字
--accent #165f49 主区交互强调(翠绿)。不用于侧栏
--accent-sidebar #8fd4b4 侧栏内的强调:active 图标、聚焦边、选中条
--primary / --primary-foreground #082d4f / #f3f8f5 主区主按钮
--primary-sidebar / --primary-sidebar-foreground #e9f0f6 / #082d4f 侧栏上的主按钮(「新建任务」)

深色与浅色下,侧栏三令牌别名到主区:--primary-sidebar 同 --primary,深色 --accent-sidebar 同 --accent。浅色侧栏是白底,--accent-sidebar 改走 --accent-text(#0b7fff 在白底上不足 4.5:1)。侧栏内的 active、聚焦和主按钮只消费这组令牌,不直接用主区 --accent / --primary。

2.6 文档纸面(主题不变量)

Office 分页预览是内容,不是界面。纸面与默认墨色固定,三套主题同值:

令牌 值 用途
--paper #ffffff docx 页、幻灯片等文档纸面
--paper-ink #000000 纸面上没有自带颜色的文字的默认墨色

规则:保留文档自己的字号、颜色、表格和图片样式。禁止用 --bg / --text 等主题令牌覆盖这些内联样式。界面只负责纸面周围的底座(--bg-inset)和按栏宽等比缩放。

3. 字号标尺(唯一字号体系)

全局唯一可调变量 --ui-font-size(默认 14px),派生:

令牌 公式 默认 角色
--fs-ui-xl +4px 18 阅读标题 h1
--fs-ui-lg +2px 16 阅读标题 h2
--fs-ui-base = 14 正文、常用按钮、区块标题
--fs-ui-caption −1px 13 紧凑辅助文案
--fs-ui-sm −2px 12 次要信息、行内代码
--fs-ui-xs −3px 11 仅徽标与图标性字符
--fs-ui-tooltip 同 --fs-ui-sm 12 提示气泡。不另起字号
--fs-code −2px 12 代码块、终端、Diff。随 --ui-font-size 缩放

规则:UI 组件一律用标尺令牌;禁止行内 font-size 数值与 Tailwind 式任意字号 (守护测试棘轮拦截)。用户调字号只改 --ui-font-size,不改根字号;图标、间距、圆角不随字号缩放。 设置中心「界面字号」提供 13 / 14 / 16 / 18 四档,写入 --ui-font-size,只存在本机(localStorage),不进账号设置。 表头用 --fs-ui-sm + --text-dim,不用 xs,也不要对中文做 uppercase。 例外:文档正文保留自己的阅读字号(约 13.5px),不跟界面标尺走。

字体:--font 系统栈优先(-apple-system/PingFang SC…);路径、命令、代码、快捷键用 --mono。

4. 间距

基数 4px。节奏:4(图标与文字)→ 8(控件内边距/行内间隙)→ 12(紧凑列表行)→ 16(卡片/面板标准内边距)→ 20–24(大区块/对话框内部)。用少量重复间距,不用任意值。

5. 圆角(按嵌套层级,不按组件重要性)

令牌 值 用途
--radius-xs 4 最内层(嵌在 6px 控件里的小元素)
--radius-sm 6 基础控件(嵌套时降档)、chip
--radius 8 输入、菜单壳、工具行
--radius-lg 12 卡片、气泡、工具调用块、面板(见 §6)
--radius-xl 16 对话框、全屏视图壳
--radius-full 999 仅用于刻意的胶囊/圆形

嵌套降档:12 → 8 → 6 → 4;最内层不低于 4。对话框内部重新从 12 起算。 禁止任意值。rounded-full 不因组件类型自动获得。

6. 布局:面板化工作区

桌面工作区 = 浮在 --bg-inset 底座上的独立圆角面板(左栏 / 对话主区 / 预览区 / 右栏): 面板 --radius-lg 圆角 + --border-soft 发丝描边,面板之间 4px 间隙,应用四周 4px 内衬。 拖拽分隔条:透明 4px 命中区,hover/拖拽时显示 2px --border-strong 指示线(两端留出面板圆角)。

预览区插在对话与右栏之间,只在当前会话有打开的文件时出现。宽度可拖(420–1100), 用 --bg,不受右栏 560 上限约束。打开第一张标签时收起右栏,关掉最后一张时恢复右栏原状。 标签按会话记住,切回该会话时恢复。

层次规则:左栏与右栏用 --bg-panel,对话主区与预览区用 --bg;窄屏可退化为通栏。 信息架构原则:对话优先——普通用户仅凭对话即可完成全部工作,右栏纯辅助、可完全收起; 系统管理类视图独立成区(管理员专属入口),不混入用户设置。

7. 海拔(Elevation)

克制深度,分层顺序:背景对比 > 发丝描边 > 浮层阴影 > 注意级阴影。

  • 基础层:无阴影,靠背景阶梯;
  • 卡片:无阴影或 --shadow-md 极弱;
  • 菜单/弹层:--shadow-md;
  • Toast/重要浮卡:--shadow-lg。

禁止用大软阴影做普通布局分层。

8. 动效(MotionKit)

动效解释状态变化,不装饰屏幕。快、低调;禁止长弹簧(仅点赞/完成反馈可用一次过冲)。 全部动效经 @ui/motion.css 的 mk-* 工具类消费;组件文件禁止私有 @keyframes (守护测试拦截)。所有动效在 prefers-reduced-motion: reduce 下禁用。

工具类 参数 用途
mk-stream-in opacity,900ms cubic-bezier(0.16,1,0.3,1) 流式内容进场(可按 token 加延迟)
mk-rise-in fade + translateY(4px),180ms 列表行/卡片进入
mk-waterfall clip-path + translateY(−12px),260ms cubic-bezier(0.22,1,0.36,1) 建议列表逐条瀑布
mk-col / mk-col-inner 高度 grid-rows 300ms ease-in-out + 内层 fade 折叠/展开(@ui Collapsible)
mk-sweep 文字扫光,300% 渐变 4s linear 运行态指示(不用 spinner)
mk-breathe opacity .4↔1,1.2s 状态点呼吸
mk-pop 450ms cubic-bezier(0.34,1.56,0.64,1) 点赞/完成过冲反馈(唯一弹性)
mk-shimmer 背景扫光 1.8s linear 加载占位
mk-overlay-in / mk-modal-in 140ms fade / 160ms fade+translateY(6px)+scale(.99) 弹层进入
mk-panel-grow flex-grow 过渡 200ms ease-out(用时挂、transitionend 摘) 面板开合

9. 组件范式

9.1 工具调用块(ToolBlock 契约,参照 ZCode ToolLayout)

单行摘要:[图标][工具名][主文本][副文本][状态词]。

  • 运行中:工具名文字扫光(mk-sweep),状态词最弱色;不用旋转图标(长流式期省渲染);
  • 完成默认收起;autoOpen(如 edit/read 类)运行时自动展开一次,用户可再收起;
  • 完成边沿(running→completed)自动收起一次,不阻止用户手动展开;
  • 展开态按 id 记忆,切回不丢;
  • 失败不强制展开:状态词虚线下划线,hover tooltip 给报错,支持一键复制;
  • 内容懒渲染,收起后延迟卸载(300ms,配合高度动画)。
  • 模型、卡片和文档里的 HTML 只经 @ui safeHtml 写入。外部图片和音视频不直接加载,改成带来源域名的链接;同源地址、data:image 和 blob: 照常显示。

9.2 折叠(@ui Collapsible 原语)

一切折叠区(过程输出、长回复、任务卡)用它:外壳高度动画 + 内容 fade 两层分离、 300ms 延迟卸载、展开态记忆。禁止再写 <details> 折叠。

9.3 一个动作一个入口

同一对象只允许一个主要操作路径:一个工件 = 一个预览落位(对话右侧预览区)+ 预览区标题栏上的一个下载。 对话里的文件卡片负责打开这个预览区;卡片菜单里的下载是同一下载动作的就近入口,不另开预览器。 全屏 overlay 是预览区的放大,不是第二落位。禁止弹窗套弹窗。

9.4 按钮

Primary(--primary 反色)、Ghost(透明,hover 出表面)、Danger(语义红)。 同一面板内保持动作层级,不把每个动作都升为 primary。

9.5 菜单与浮层

菜单壳 --radius(8) + --shadow-md + 紧凑行(--radius-sm 6 的行、--fs-ui-base); 菜单是紧凑动作行,不是迷你按钮。交互浮层必须盖过被动 tooltip。

9.6 工作时间线与标签条

助手消息在运行中按时间线逐行展开,终轮结束后折成一行。

  • 运行中过程块展开,块头是中文阶段(思考中、正在编写、正在运行并计时、回复中、整理回复中),带 mk-sweep。 对用户的解说按正文样式直接显示。查阅和搜索合并成一行;执行、写入、委派每次一条 ToolBlock: 编写参数时显示「编写中」和脚本尾部,运行时显示计时和输出尾部,结束后可展开看完整参数与结果。 终轮检查在过程区单独一行(通过,或未通过及原因),不写进给用户的回复。
  • 终轮结束后,过程段收进 Collapsible,触发行为「已工作 X 分 Y 秒 · N 次工具调用 · N 个文件」。 用户在运行中手动折过的,结束后沿用这次选择。最终回复(终轮正文、交付物、错误)留在折叠行下面; 交付物卡片等到最终回复出来、这一轮结束后才出现,工作过程中不挂预览条。 若这次没有终轮正文,把最后一段解说提到折叠行下面,不把回复藏进过程里。 不在每一轮 responding 时来回折叠。同一轮同名工件只留最新一张,并注明更新次数。
  • 文件卡片:图标、名称、「类型 · 大小」、右侧「预览」。正文里的 art_ 编号若对得上工件,在正文后补一张卡片; 对不上则显示「未找到该文件」,不伪装成可打开的文件。
  • 标签条用 @ui TabStrip:点击激活、× 关闭、中键关闭,溢出横向滚动。只消费令牌与 mk-*。

10. 信息架构与文案

  • 普通用户界面只暴露任务与对话;插件/代理/治理类能力归系统管理区(管理员可见)。
  • 右栏收起时功能零缺失(D31:弹层不承载唯一步骤,每个操作另有对话内路径)。
  • 中文文案:动宾结构、不带句点结尾;快捷键用 ⌘/kbd 标注。
  • 布局按 --text-expansion(1.3)给按钮和标签留膨胀空间。不要把宽度定死成当前中文的字数。截断不是唯一生存手段。

10.1 快捷键

动作 按键
新建任务 ⌘N / Ctrl+N
折叠或展开左栏 ⌘B / Ctrl+B
打开第 n 个工作区 ⌘1–9 / Ctrl+1–9

11. 禁止清单(守护测试覆盖项)

  1. 组件/样式文件里新增裸色值(hex/rgb 字面量)——走令牌;
  2. 组件文件里私有 @keyframes——走 MotionKit;
  3. TSX 行内 font-size——走字号标尺;
  4. 运行态用旋转 spinner——用 mk-sweep/mk-breathe;
  5. 弹窗套弹窗;
  6. 同一对象出现第二个预览落位(预览只在预览区,全屏是它的放大);
  7. <details> 折叠——用 Collapsible。
  8. 绕过 safeHtml 直接把 HTML 字符串写进页面(dangerouslySetInnerHTML 或非空的 innerHTML 赋值)。
  9. 文字与背景的对比度低于门槛(正文与文字档 4.5:1,装饰 faint 与图形语义色 3:1)——contrast-guard.test.ts。

12. 演进规则

改风格须在同一变更集中成对修改:UI 仓 PR 调整 tokens.css(必要时 motion.css), Dev 组合 PR 更新 DESIGN.md 并固定对应 UI 提交;两者互链,附前后值对照并验证精确组合。 不允许只改代码不改文档。新增视觉规则先问:它属于结构、表面、交互还是状态? 拿不准时,选更安静的方案、用更强的信息层级。

12.1 对比度与字号(2026-10-05)前后值

令牌 之前 之后
--text-dim 三主题 62% 深 66% / 浅 68% / 墨绿 70%
--text-faint 深 38% / 浅与墨绿 42% 深 52% / 浅与墨绿 58%
--text-sidebar-dim / faint(墨绿) 72% / 46% 78% / 62%
--warn(浅色、墨绿) #e07b00(白底 2.99:1) #d17300
--fs-ui-xs −4px(10px) −3px(11px),仅徽标
文字档 *-text、--text-on-semantic、--accent-sidebar、--primary-sidebar、--fs-code、--idle-text 无 见 §2.4–§3。图形色不再当文字用