Files
ycode/design-system.md
xiaohan.yuan 3ceae1e983 chore(design-system): add extraction artifact and token drift gate
Record the design decisions actually in use and add a static gate that blocks new bare colors, bare sizes, important overrides, and wb token definitions outside token sources.
2026-10-18 18:36:43 +08:00

43 KiB
Raw Permalink Blame History

YCode 设计系统现状(Extract,2026-10-18)

本文件是现状快照,不是目标方案。 只记录当前仓库里实际生效的 token、刻度、组件与约定,供后续 Build / Audit 逐条对照。 目标分层、兼容层边界与迁移顺序见 docs/设计系统提取与统一方案-2026-10-18.md(本文件第 6 节只做指向,不复制方案内容)。 采集范围:src/renderer/src(统计时排除第三方资产目录 workbuddy/artifacts/recovered-pierre/、workbuddy/workbench/source-code-assets/)与构建产物 out/renderer/。 采集方式:rg 文本检索 + 正则统计 + PowerShell 逐字节读取文件;未做浏览器运行时取值,未改动任何实现文件。 工作树快照说明:提取期间同批 P0 工作已落地 scripts/check-design-tokens.mjs、scripts/design-token-baseline.json(npm run check:tokens)并更新 scripts/verify-ui.mjs;本文件第 5.5 / 6 节按当前工作树(含这些未提交改动)记录。

0. 规模与测量基线

指标 实测值 说明
CSS 文件 / TSX 文件 109 / 151 src/renderer/src 全量,含恢复层
CSS 行数 19,790 逐文件 Get-Content 行数求和
var(--yc-*) 引用 1,372 与方案文档记录的 1,372 一致
var(--wb-*) 引用 22,766 方案文档记录 22,756(本文件实测多 10 处)
!important 926 方案文档记录 925(本文件实测多 1 处)
tokens.css 中 --yc-* 声明 271 :root 229 + html[data-theme='dark'] 18 + .cb-font-size-fixed 24
workbuddy/typography/tokens.css 中 --wb-* 声明 115 唯一的根级 --wb-* 家族(排版/间距)
原生控件 <button> 362 / <input> 48 / <textarea> 8 / <select> 2 TSX 内直接书写
内联 <svg> 164(其中 69 个在 *Icons.tsx 模块内) 图标模块共 25 个
wb-button 类出现(TSX) 247 次,分布在 18 个文件 变体计数见 3.1
本地 className="btn…" 12 处 见 3.2

1. 权威来源:谁在根级生效,谁只是作用域闭包

1.1 根级生效的层

层 位置(选择器) 内容 声明数
YCode 权威 token src/renderer/src/styles/tokens.css:17 :root 调色板、语义色、间距/字号/行高/字重、控件尺寸、圆角、字体族、布局、描边、阴影、动效、字号档位 229
深色重映射 src/renderer/src/styles/tokens.css:352 html[data-theme='dark'] 只重映射 text/bg/border/气泡/阴影;未列出的沿用浅色 18
根级 WB 排版 token src/renderer/src/workbuddy/typography/tokens.css:5 :root --wb-spacing-*、--wb-font-size-*、--wb-font-line-height-*、--wb-font-weight-*、语义体例(body/caption/code/h1-h3/display/spec-/chatflow-)、--wb-button-{height,font-size,line-height,icon-size}-* 115
固定字号边界重解析 src/renderer/src/styles/tokens.css 末尾 .cb-font-size-fixed, .cb-font-size-fixed * 在内层把 --yc-text-* 重新指回 --wb-font-*,避免全局字号档位重复叠加 24

依赖方向(实测):

  • --yc-space-1…10/12 全部 var(--wb-spacing-N);例外 --yc-space-11: 56px 是硬写(WB 无 --wb-spacing-11)。
  • --yc-font-size-1…11、--yc-font-weight-400/500/600/700、大部分 --yc-line-height-* 均指向 --wb-font-*;例外 --yc-line-height-6-2: 26px 是硬写(WB 无该 token,见 5.3)。
  • --yc-font-mono: var(--wb-font-mono) → --wb-font-code-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace。
  • --yc-text-body/caption/code/h1/h2/h3/display-* 全部 var(--wb-font-*) 别名,是 YCode 侧唯一一层"语义字号"入口。

1.2 --wb-*:除排版外全部是"按作用域复制的兼容闭包"

根级只定义了 115 个排版/间距 token;颜色、圆角、控件尺寸、按钮/输入/弹窗等 --wb-* 在根上没有定义,而是各页面/组件在自己的 subtree 里整份复制。实测 --wb-palette-brand-8: 在 13 个 CSS 文件里被重复声明:

作用域(已逐行核验) 文件:行
.yc-capability-center src/renderer/src/capabilities/capability-center-source.css:2
.models-settings-panel src/renderer/src/components/model-settings.css:146
.source-home src/renderer/src/components/source-home-recovered.css:2
.source-workspace-picker src/renderer/src/components/source-workspace-picker-recovered.css:2
.chat-pane.cr-theme src/renderer/src/workbuddy/conversation/source-styles.css:7
(其余 8 个文件同族复制) components/settings-shell-source.css、components/workspace-source.css、components/source-general-settings-recovered.css、components/source-settings-navigation-recovered.css、components/source-select/source-select-recovered.css、projects/source-project-controls.css、workbuddy/composer/add-menu/source.css、workbuddy/composer/model-selector/source.css、workbuddy/subagents/theme.css

闭包缺失的直接后果(可复现):

  • --wb-size-control-sm/ms/md/lg/xl/2xl、--wb-icon-size-sm/ms/md/lg/xl 只在这些作用域内定义(例:capability-center-source.css:8、model-settings.css:146、workbuddy/conversation/source-styles.css:7),根上没有。
  • 因此排版 token 里的 --wb-button-height-small: var(--wb-size-control-sm)、--wb-button-icon-size-medium: var(--wb-icon-size-md) 等,只有在某个闭包作用域内才会解析成功;出作用域即失效。
  • --wb-font-line-height-9、--wb-font-line-height-6-2 被 7 个 CSS 文件引用(var(--wb-font-line-height-9)、var(--wb-font-line-height-6-2)),但全仓库没有任何定义;--wb-font-spec-h2-line-height、--wb-font-spec-h5-line-height 同样指向未定义项。

恢复层命名家族(用于判断"这段 CSS 来自哪里"):

前缀 / 形态 含义 唯一选择器数(实测)
cr-* 会话渲染恢复层(chat renderer) 591
cb-* 原版通用组件层(button/checkbox/input/…) 204
ec-* 能力中心/专家中心恢复层 227
sm-* 本地技能/市场页面 274
dc-* 抽屉/面板少量恢复规则 6
_name_hash_index 原版 CSS Module 哈希类名(如 ._about_385qb_250、._dialogOverlay_peiew_7、._icon_vnue1_21) 大量

1.3 CSS 加载顺序与冲突点

声明的顺序(源码为准):

入口 顺序
src/renderer/src/main.tsx:5-10 workbuddy/typography/tokens.css → styles/tokens.css → styles/app.css → styles/sidebar.css → workbuddy/conversation/source-styles.css → workbuddy/conversation/source-adapters.css
src/renderer/src/settings.tsx:4-6 workbuddy/typography/tokens.css → styles/tokens.css → styles/app.css → styles/settings-entry.css

组件级追加(在入口之后由组件模块自带,顺序受模块求值影响):

文件:行 导入
src/renderer/src/App.tsx:19-21 panel-motion-source.css、drawer-motion-source.css、panel-layout-adapters.css
src/renderer/src/components/Sidebar.tsx:34-35 workspace-source.css、sidebar-shell-source.css
src/renderer/src/components/SettingsDialog.tsx:7-11 source-select/source-select-recovered.css、source-select/source-select.css、source-general-settings.css、settings-shell-source.css、../styles/settings-entry.css
src/renderer/src/components/ChatPane.tsx:8 workbuddy/conversation/search-highlight-adapters.css
src/renderer/src/capabilities/CapabilityCenter.tsx:9 capability-center-source.css
src/renderer/src/components/SourceHome.tsx:7 source-home.css(其第 1 行 @import './source-home-recovered.css')
src/renderer/src/components/ModelSettingsPanel.tsx:9-10 model-settings.css、custom-model-settings.css
src/renderer/src/projects/ProjectListPage.tsx:11-13 source-project-controls.css、source-projects-recovered.css、project-layout.css

构建产物实测(out/renderer/,与"声明顺序"并不一致):

  • out/renderer/index.html 只挂 2 个样式表,且顺序为 app-h0tta3aw.css → index-C92zurN-.css。
  • app-h0tta3aw.css 的第一条规则是恢复层 .source-select-host{--wb-palette-…},来自 SettingsDialog.tsx 的导入;--yc-* 根块出现在约 178.6 KB 处,晚于 .settings-modal-overlay(约 152.5 KB)。
  • styles/sidebar.css(.sidebar__brand-block 约 2.87 MB)与 .chat-pane.cr-theme(约 2.89 MB)落在第二个样式表 index-C92zurN-.css 里。

冲突点清单:

  1. 声明顺序 ≠ 生效顺序:main.tsx 的 import App / import { SettingsWindow } 写在样式导入之前,打包后组件自带 CSS 先于入口样式落地。
  2. 同特异性并列时由后加载者获胜(本地 .btn 与恢复 wb-button 在同一元素上并用时需要显式顺序,styles/app.css 与 sidebar-shell-source.css 都定义过按钮外观)。
  3. 作用域闭包不可迁移:把元素移出 .source-home / .models-settings-panel / .chat-pane.cr-theme 等宿主后,--wb-* 立即失配。
  4. 深色主题按作用域各写一遍:html[data-theme='dark'] …scope… 与组件自带的 .dark/.vscode-dark 兼容分支同时存在,优先级取决于加载顺序。

1.4 --yc-* 也不是严格单源

位置 重新声明的变量 原因(文件内注释)
src/renderer/src/styles/sidebar.css:14-15 .sidebar --yc-font-sans、--yc-text-primary 侧栏保留原版 shell 回退栈
src/renderer/src/styles/sidebar.css:29-36 html[data-theme='dark'] .sidebar --yc-bg-secondary、--yc-bg-hover、--yc-bg-active、--yc-text-*、--yc-border-tertiary 暗色侧栏用 #1f1f1f 而非全局 #171717
src/renderer/src/styles/sidebar.css:708-710 .notif-panel --yc-notif-bg/-border/-title 通知面板局部 token
src/renderer/src/components/task-menu.css:21-26,41-46 .conversation-context-menu --yc-task-menu-* Portal 不在 .chat-pane.cr-theme 内,显式给同值
src/renderer/src/projects/project-menu.css:3-6,21-24 .yc-project-more --yc-project-menu-* Portal 不继承侧栏 token
src/renderer/src/App.tsx:396(内联 style) --yc-layout-main 运行时计算主列宽度;由 workbuddy/workbench/panel-layout-adapters.css:2 消费

2. 实际生效的 scales(只列组件真正在用的步骤)

计数列 = 该 token 在 src/renderer/src(CSS/TSX/TS)中的出现次数,含 tokens.css 自身的别名定义,用于说明"这一步确实被消费"。

2.1 颜色:中性阶(来源 styles/tokens.css:19-36)

Token 值 计数
--yc-black-100 #000000 5
--yc-black-70 / -50 / -30 / -20 / -15 / -10 rgba(0,0,0,.7/.5/.3/.2/.15/.1) 各 1–2
--yc-white-100 #ffffff 9
--yc-gray-1 #fafafa 2
--yc-gray-2 #f7f7f7 2
--yc-gray-3 #f2f2f2 2
--yc-gray-4 #ebebeb 2
--yc-gray-5 #e6e6e6 3
--yc-gray-6 #dedede 2

2.2 品牌与状态色

Token 浅色值 深色处理 计数
--yc-brand-8 #00c29a 不重映射(恢复层深色用 #4cf0ce) 13
--yc-brand-soft #dff7f2 不重映射 1
--yc-green-8 #0cbf5b 不重映射 1
--yc-orange-8 #ff7800 不重映射 1
--yc-red-8 #f64041 不重映射 3
--yc-blue-8 #3370ff 不重映射 2
--yc-status-success / warning / error / info 即 green/orange/red/blue-8 别名 同左 9 / 7 / 29 / 5

恢复层同一时刻的 palette 值(capability-center-source.css:2 与其 dark 分支):--wb-palette-brand-8 浅色 #00c29a、深色 #4cf0ce;gray-3/4/5 浅色 #f2f2f2/#ebebeb/#e6e6e6、深色 #1f1f1f/#242424/#3a3a3a。

2.3 语义色(浅色 → 深色)

Token 浅色 深色(html[data-theme='dark']) 计数
--yc-text-primary rgba(0,0,0,.9) rgba(255,255,255,.9) 99
--yc-text-secondary rgba(0,0,0,.7) rgba(255,255,255,.7) 80
--yc-text-tertiary rgba(0,0,0,.5) rgba(255,255,255,.5) 74
--yc-text-disabled rgba(0,0,0,.3) rgba(255,255,255,.3) 3
--yc-text-inverse #ffffff #1f1f1f 2
--yc-bg-primary #ffffff #1f1f1f 56
--yc-bg-secondary #f7f7f7 #171717 27
--yc-bg-tertiary #f2f2f2 #242424 8
--yc-bg-hover #ebebeb #2a2a2a 39
--yc-bg-active #e6e6e6 #333333 6
--yc-bg-scrim rgba(0,0,0,.35) rgba(0,0,0,.6) 2
--yc-border-primary #e6e6e6 #333333 46
--yc-border-secondary #ebebeb #2a2a2a 5
--yc-border-tertiary #f2f2f2 #242424 4
--yc-border-strong #dedede #3d3d3d 3
--yc-bubble-user-bg #f2f2f2 #2f2f2f 2

2.4 间距阶(--yc-space-* = --wb-spacing-*)

步骤 值 计数 步骤 值 计数
space-1 2px 24 space-7 24px 5
space-2 4px 41 space-8 32px 2
space-3 8px 60 space-9 40px 7
space-4 12px 44 space-10 48px 2
space-5 16px 22 space-11 56px(硬写) 1
space-6 20px 14 space-12 64px 8

恢复层同时高频使用 --wb-spacing-* 本体(-1 282、-2 354、-3 508、-4 313、-5 288、-6 99、-7 90、-8 73、-9 26、-10 45、-12 46,另有 -0 15、-2-5 53)。

2.5 字号 / 行高 / 字重

字号阶(--yc-font-size-N,计数含定义):

N 1 2 3 4 5 6 7 8 9 10 11
px 8 10 12 13 14 16 18 20 24 28 32
计数 1 10 23 10 15 4 9 2 1 1 1

行高阶(--yc-line-height-*):4:16、4-2:18、5:20、5-2:22、6:24、6-2:26(硬写)、7:28、8:32、10:40。

字重:400 / 500 / 600 / 700。

语义体例(--yc-text-* → --wb-font-*,size/line-height/weight):

体例 值 计数(size)
body 14 / 22 / 400 21
body-strong 14 / 22 / 600 3
caption 12 / 18 / 400 36
code 13 / 20 / 400 3
h1 24 / 32 / 600 1
h2 20 / 28 / 600 2
h3 16 / 24 / 600 2
display 32 / 40 / 700 1

对话流(chatflow,独立一套,默认 offset=0,实际值 = calc(基准 + var(--yc-font-offset) × 倍率)):h1 21/37、h2 19/33、h3 17/30、h4 15/26、p1 15/26、p2 13/23、p3 11/19。

Markdown 正文:根字号 --yc-md-root: 17.143px、行高 1.75、段落 0.875em、行内代码 12.857px / 22.5px。

字体族:--yc-font-sans: 'PingFang SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;--yc-font-mono 继承 ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace。

全局字号档位(src/renderer/src/fontSize.ts + tokens.css 末尾):

档 mdRoot offset
1 16px -1
2(默认) 17.143px 0
3 18.286px +1
4 20.571px +2
5 22.857px +3(仅正文放大)
6 26.286px +4(仅正文放大)

--yc-font-offset-global 由 JS 写入,控件侧统一夹取 --yc-font-offset: clamp(-1, var(--yc-font-offset-global), 2)。

2.6 控件尺寸阶

Token 值 计数 Token 值 计数
--yc-size-3 12px 3 --yc-size-10 40px 4
--yc-size-3-2 14px 5 --yc-size-11 44px 1
--yc-size-4 16px 9 --yc-size-12 48px 2
--yc-size-5 20px 5 --yc-size-13 52px 1
--yc-size-6 24px 7 --yc-size-14 56px 2
--yc-size-7 28px 11 --yc-size-17 68px 1
--yc-size-8 32px 2 --yc-size-9 36px 1

语义控件高度:--yc-control-sm:24、ms:28、md:32、lg:40、xl:48、2xl:56;实际消费 control-md 18 次、control-xl 3 次、control-2xl 2 次、control-ms 2 次、control-sm/lg 各 1 次。

2.7 圆角阶

Token 值 计数 Token 值 计数
--yc-radius-none 0 1 --yc-radius-xl 12px 7
--yc-radius-xs 2px 4 --yc-radius-2xl 16px 6
--yc-radius-sm 4px 8 --yc-radius-3xl 20px 1
--yc-radius-md 6px 16 --yc-radius-4xl 24px 2
--yc-radius-lg 8px 29 --yc-radius-full 9999px 16
语义:--yc-radius-bubble 16px 3 --yc-radius-input 24px 2

恢复层圆角集合与之一致(capability-center-source.css 实测出现 0/2/4/6/8/12/16/20/24/9999px)。

2.8 阴影

Token 浅色值 深色值 计数
--yc-shadow-input rgba(0,0,0,.03) 0 16px 32px -8px, rgba(0,0,0,.06) 0 2px 4px -4px 0 1px 2px rgba(0,0,0,.3), 0 4px 12px rgba(0,0,0,.35) 3
--yc-shadow-popover 0 4px 16px rgba(0,0,0,.1) 不重映射 1
--yc-shadow-dialog 0 12px 32px rgba(0,0,0,.16) 0 12px 32px rgba(0,0,0,.5) 1

2.9 动效

Token 值 计数
--yc-motion-fast 0.1s 3
--yc-motion-medium 0.15s 1
--yc-motion-slow 0.2s 1
--yc-motion-easing cubic-bezier(0.4, 0, 0.2, 1) 1

恢复层使用自己的时长/缓动闭包(实测出现值):时长 .1s / .15s / .2s / .3s / .4s,缓动 cubic-bezier(.2,0,0,1)、cubic-bezier(.4,0,.2,1)、cubic-bezier(.4,0,1,1)、cubic-bezier(0,0,.2,1)、linear。

2.10 布局常量

Token 值 计数 备注(来源文件内实测说明)
--yc-layout-sidebar-expanded 280px 2 实测 @1334 窗口;@1276 实测为 240px,宽度本身可变
--yc-layout-sidebar = expanded 5 当前展开默认
--yc-sidebar-rail-width 44px 1 收起后的窄轨
--yc-layout-right 647px 4 详情面板实测宽
--yc-layout-right-min 320px 1 最小宽
--yc-content-max 832px 4 .cr-message-list__content
--yc-content-inline-pad 40px 1 --yc-space-9
--yc-input-max 784px 6 .cr-input-box
--yc-titlebar-height 30px 6 顶部条带
--yc-titlebar-leading 92px 3 左侧操作区
--yc-window-control-width 46px 2 单钮宽
--yc-titlebar-menu-min-width 200px 2 菜单最小宽
--yc-window-control-icon 10px 3 窗口控制图标
--yc-dialog-width / -narrow-width 560px / 420px 1 / 1 对话框

2.11 实测一次性常量(非标准阶,具名后组件不写裸像素)

选取后续组件最常复用的一组(全部定义在 styles/tokens.css「实测常量」段):

Token 值 Token 值
--yc-scrollbar-size 6px --yc-input-min-height 96px
--yc-scrollbar-thumb-alpha 0.2 --yc-input-editor-min-height 64px
--yc-resizer-hit 6px --yc-input-max-height 200px
--yc-sidebar-item-height 31px --yc-input-box-white-height 144px
--yc-sidebar-section-label-height 30px --yc-input-editor-home 74px
--yc-sidebar-section-head-height 34px --yc-input-footer-row 40px
--yc-sidebar-tab-height 32px --yc-prompt-row-height 38px
--yc-sidebar-footer-height 57px --yc-prompt-row-step 50px
--yc-discover-height 28px --yc-msg-header-height 24.5px
--yc-user-menu-height 40px --yc-bubble-max-height 310px
--yc-user-avatar-size 28px --yc-tool-body-max-height 320px
--yc-icon-btn-sm / -md 24px / 32px --yc-panel-tab-min-width / -max-width 80px / 240px
--yc-badge-size / -offset 14px / 2px --yc-home-content-width 800px
--yc-segmented-height 32px --yc-home-quick-actions-width 680px
--yc-segmented-item-width 72px --yc-home-title-size / -line-height 30px / 42px
--yc-dialog-width 560px --yc-empty-desc-max-width 324px
--yc-line-height-19 / -21 / -245 / -2625 19 / 21 / 24.5 / 26.25px --yc-letter-spacing-badge 0.2px

3. 组件清单

层级标记:[Y] = YCode 自有实现;[R] = REA 恢复组件(生成物,勿手改);[L] = 本地旧类/一次性实现(迁移目标见第 6 节)。

3.1 可复用组件矩阵

组件 代码 path 类名 / 变体 层级 备注(实测)
Button / IconButton src/renderer/src/components/task-confirm-dialog.tsx、components/SourceChatHeader.tsx、components/ArchivedTasksDialog.tsx、workbuddy/user-menu/AccountMenu.tsx、projects/ProjectDetailPage.tsx、capabilities/*Page.tsx wb-button + --primary(16) / --secondary(23) / --grey(未用) / --ghost(13) / --link(3) / --danger(4) / --icon(9) / --circle(5) / --loading(2) / --disabled(2) / --full(1);尺寸 --small(14) / --medium(41) / --xsmall(1);内部 wb-button__content(24)、wb-button__icon(29) [R] 样式(各 scope 闭包) + [Y] 调用点 共 247 次类名出现 / 18 个 TSX 文件;<button> 原生 362 个
IconButton(本地) src/renderer/src/styles/app.css:934-949、components/Sidebar.tsx:346、components/NotificationsPanel.tsx:148 .btn-icon [L] 与 wb-button--icon/circle 并存的第三套图标按钮
Button(本地) src/renderer/src/styles/app.css:949-981 .btn、.btn--primary、.btn--ghost [L] 12 处 TSX 使用:components/AboutDialog.tsx:50/53、components/ChatPane.tsx:499-526、components/SettingsDialog.tsx:80
Button(页面级) src/renderer/src/automations/automation-page.css .automation-button、--primary / --secondary / --danger [L] 自动化页专用
Input / Textarea components/ModelSettingsPanel.tsx、components/EditableModelSelect.tsx、components/WorkspaceDialog.tsx、components/SourceWorkspacePicker.tsx、capabilities/ExpertsPage.tsx、projects/ProjectListPage.tsx wb-input、wb-input-wrapper、wb-input__inner / __prefix / __suffix / __clear / __icon-button / __count / __tips、wb-input--filled / --status-error / --with-affix、wb-input-wrapper--small/medium/filled/disabled、wb-input-group__addon;文本域 wb-textarea [R] 样式 + [Y] 调用点 <input> 48、<textarea> 8
Textarea(本地) projects/ProjectInstructionDrawer.tsx:25、capabilities/ConnectorsPage.tsx:25、components/MemorySettingsPanel.tsx:293/472、components/PersonalizationSettingsPanel.tsx:336 .project-instruction-drawer__textarea、.mcp-config-textarea、.memory-settings-panel__manage-editor、.local-memory-editor [L] 四套局部文本域样式
Select components/source-select/SourceSelect.tsx(宿主,渲染 <span class="source-select-host">)、components/source-select/RecoveredSelectCore.tsx、components/source-select/SourceSelectPopover.tsx wb-select__panel / __list / __option / __option--selected / __option--single-selected / __option-label / __empty、wb-select-popover;宿主 props:size: small/medium/large、shape、placement、showSearch、allowClear、portalRoot [R] 核心 + [Y] 包装 另有 components/EditableModelSelect.tsx、components/SourceModelPicker.tsx(.source-model-picker)
Select(原生) src/renderer/src/automations/AutomationRecords.tsx:100,112 <select> [L] 全仓库仅 2 处
Dialog components/task-confirm-dialog.tsx + components/task-confirm-dialog.css、components/ArchivedTasksDialog.tsx + .css、components/WorkspaceDialog.tsx + components/workspace-source.css、components/SettingsDialog.tsx + components/settings-shell-source.css wb-modal、wb-modal__overlay / __overlay--center / __header / __header-row / __title / __title-wrap / __body / __footer / __footer--right / __footer-actions / __close、wb-modal-anim-open;设置页用 .settings-modal、.settings-modal-overlay [R] 另有 components/AboutDialog.tsx(本地 .dialog)、workbuddy/composer/permission/SourcePermissionControl.tsx(确认弹窗)
Popover / Menu components/AppDiscoverPopover.tsx + components/app-discover-popover.css、workbuddy/user-menu/AccountMenu.tsx + account-menu-source.css、components/task-menu.tsx + task-menu.css、projects/ProjectMenu.tsx + project-menu.css、components/source-select/SourceSelectPopover.tsx wb-popover、wb-popover--placement-top、wb-dropdown、wb-dropdown__item / __list / __label / __check / __icon / __search / __scroll / __footer、wb-dropdown--single / --scrollable;YCode 侧 .yc-project-more、.conversation-context-menu [R]+[Y] 侧栏菜单在 .chat-pane.cr-theme 之外,task-menu.css 显式给出等价 token
Tabs / Segmented components/SourceSettingsNavigation.tsx + components/settings-shell-source.css(.settings-navigation__item 等)、components/Sidebar.tsx:369-415 + styles/sidebar.css(.conversation-list-tab-button)、components/SourceHome.tsx(.wb-scene-tabs,样式在 source-home-recovered.css)、capabilities/ExpertsPage.tsx Segmented:wb-segmented、wb-segmented__item / __item--active / __item-label / __thumb / __thumb--measured;Tabs:conversation-list-tab-button、wb-scene-tabs__pill [R] 样式 + [Y] 容器 无 wb-tabs 类(全仓库 0 次);Segmented 尺寸 token 见 2.11
Checkbox components/source-select/RecoveredSelectCore.tsx、components/ModelSettingsPanel.tsx、workbuddy/composer/permission/SourcePermissionControl.tsx wb-checkbox、__box / __control / __former / __icon / __input / __label、--checked / --disabled / --indeterminate / --readonly [R] 样式闭包在 model-settings.css、source-select-recovered.css、source-permission-recovered.css
Switch components/GeneralSettingsPanel.tsx、components/MemorySettingsPanel.tsx、components/PersonalizationSettingsPanel.tsx、workbuddy/composer/permission/SourcePermissionControl.tsx、capabilities/SkillsPage.tsx wb-switch、__track / __thumb / __input、--small / --large / --danger [R] 主要样式与主题化在 components/settings-shell-source.css
Card components/ModelSettingsPanel.tsx(.models-settings-panel__card,model-settings.css:6)、components/AppearanceSettingsPanel.tsx(.appearance-card,source-appearance-panel-recovered.css)、components/Sidebar.tsx(.conversation-list-invite-friends__card,sidebar-shell-source.css)、components/ToolCard.tsx(.tool-card*,styles/app.css:425+)、workbuddy/conversation/MessageQuoteCard.tsx(.cr-input-quote-card*,message-quote-source.css)、capabilities/ExpertsPage.tsx(.expert-card,expert-source.css) 无统一 Card 组件;无 wb-card 类(0 次) 混合 6 套独立卡片样式
ListItem / NavItem components/SourceWorkspacePicker.tsx(wb-dropdown__item)、components/SourceSettingsNavigation.tsx(.settings-navigation__item)、components/Sidebar.tsx(.sidebar__item*、.conversation-item,styles/sidebar.css + components/workspace-source.css)、capabilities/SkillsPage.tsx(wb-dropdown__item) wb-dropdown__item--selected / --empty、.settings-navigation__item--active、.sidebar__item--menu-open [R]+[Y] 侧栏列表项几何:31px 高、padding 5px 12px(tokens.css 注释实测)
Badge / Tag 使用点:components/Sidebar.tsx:369/415/596(.sidebar__version-badge、.conversation-list-version-badge、.sidebar__tab-beta、.msg-center-badge)、capabilities/ConnectorsPage.tsx:84(.mcp-installed-badge)、projects/ProjectDetailPage.tsx:527(.task-item__source-badge)、components/AppearanceSettingsPanel.tsx:41(.appearance-badge--validity)、components/ModelSettingsPanel.tsx:224(models-settings-panel__connection-failed-badge) 无统一 Badge;wb-tag 仅在 capabilities/expert-source.css、components/workspace-source.css 有样式,TSX 无使用 混合 styles/app.css:1417-1443 还有无双基 .badge / .badge--ok / .badge--warn,TSX 未使用
EmptyState capabilities/ExpertsPage.tsx(.capability-expert-empty,expert-source.css;插图 capabilities/assets/empty-created-expert.svg)、components/Sidebar.tsx(.conversation-list-empty、.sidebar__empty,sidebar-shell-source.css / sidebar.css)、automations/AutomationPage.tsx(.automation-empty-state)、library/LibraryPage.tsx(经 library.css .library-feed-empty、.library-local-empty) 每页各写一套;恢复层另有 colleague-chat-empty-profile(styles/tokens.css 中记录其 gap/尺寸实测) 混合 无 wb-empty 类(0 次)
Avatar components/SourceAgentAvatar.tsx(REA 生成的固定 SVG,ev_d6e6920f…)、workbuddy/user-menu/AccountMenu.tsx(用户头像,28px,--yc-user-avatar-size)、components/MessageBubble.tsx(.assistant-avatar,workbuddy/conversation/source-styles.css)、workbuddy/subagents/*(.yc-member-avatar,subagents/adapters.css) .wb-avatar 样式仅在 projects/source-project-detail-recovered.css 与 styles/tokens.css 注释中出现;无 wb-avatar JSX 使用 混合 .avatar*/avatar-item 等类名还散落在若干页面
Spinner components/ArchivedTasksDialog.tsx(.archived-tasks-spin)、automations/AutomationPage.tsx(.automation-running-spinner)、workbuddy/artifacts/ArtifactContentRenderer.tsx、workbuddy/mermaid/MermaidBlock.tsx(.loading-spinner)、workbuddy/conversation/MessageEditorIcons.tsx(.cr-input-spin)、workbuddy/subagents/*(.yc-member-spinner) 关键帧:wb-icon-spin(components/source-select/source-select-recovered.css);无 wb-spinner 类 混合 各模块自带旋转样式
Skeleton library/LibraryPageParity.tsx(.library-skeleton、.library-feed-skeleton、.library-local-skeleton,library/library.css)、components/sidebar-shell-source.css(.conversation-list-skeleton)、capabilities/connectors-source.css(.connector-skeleton*)、components/settings-panel-loader.tsx + styles/settings-entry.css(.settings-panel-loading) 无 wb-skeleton 类 [Y]+[R] 4 套骨架模式
Tooltip components/source-select/RecoveredSelectTooltip.tsx、workbuddy/composer/context-info/ComposerContextInfo.tsx:189(wb-tooltip wb-tooltip--placement-top wb-tooltip--fade-open、wb-tooltip__content / __arrow)、workbuddy/conversation/UserMessageEditor.tsx:20(选择器白名单引用 .wb-tooltip) wb-tooltip--placement-* / --interactive / --no-padding / --fade-*;token:--wb-tooltip-z-index:1070(运行时兜底) [R] 样式闭包在 sidebar-shell-source.css、source-select-recovered.css、composer/context-info/source.css、composer/model-selector/source.css、conversation/question-source.css
Toast / Notice components/ModelSettingsPanel.tsx:219(.model-ui-toast,model-settings.css:406,fixed 顶部居中、z-index 1200)、capabilities/SkillsPage.tsx:107(.yc-skill-notice / .yc-skill-error,skills-host.css)、workbuddy/subagents/SubagentDetailPanel.tsx:72-75 与 components/RightSidebar.tsx:32(.yc-member-notice,subagents/adapters.css)、workbuddy/message-actions/MessageActionToolbar.tsx(.wb-message-actions__pending / __error) 无统一 Toast;恢复层只保留 --wb-message-* token(capability-center-source.css 闭包内),无 JSX 宿主 混合 styles/app.css:1448-1462 的 .notice(含 dark 规则)在 TSX 中查无使用

3.2 有样式、无 JSX / 已废弃的入口

项 位置 现状
.notice styles/app.css:1448、:1458(dark) TSX 无 className="notice"
.badge / .badge--ok / .badge--warn styles/app.css:1417-1443 TSX 无使用
wb-tag capabilities/expert-source.css、components/workspace-source.css 只有恢复样式,无 TSX 宿主
--wb-message-*(Toast/Message 组件 token) capabilities/capability-center-source.css 只有 token 闭包,无组件宿主
.input / .input--mono、.dialog / .dialog__actions、.menu-dropdown* styles/app.css 本地旧类;.dialog 由 components/AboutDialog.tsx、components/ChatPane.tsx 使用,.menu-dropdown* 由 components/TitleBar.tsx 使用

3.3 图标与原生控件现状

  • 图标模块 25 个(components/icons.tsx、components/icons-extra.tsx、components/general-settings-icons.tsx、components/task-menu-icons.tsx、components/SourceChatHeaderIcons.tsx、components/source-select/SourceSelectIcons.tsx、capabilities/{ConnectorSourceIcons,SkillSourceIcons}.tsx、library/{LibraryIcons,SourceLibraryIcons,SourceLibraryChromeIcons}.tsx、automations/automation-source-icons.tsx、projects/ProjectIcon.tsx、workbuddy/**/{*Icons,icons,account-menu-icons}.tsx)。
  • 内联 <svg> 164 个,其中仅 69 个位于 *Icons.tsx,其余内联在页面/组件里。
  • 原生控件:<button> 362 / <input> 48 / <textarea> 8 / <select> 2(automations/AutomationRecords.tsx)。
  • wb-icon 类在多个恢复闭包中有独立尺寸规则(例:source-select-recovered.css 中 .wb-icon 与 wb-icon--spin 动画)。

4. 约定(当前实际遵守 / 未遵守的规矩)

主题 现状 证据
类名体系 四类并存:wb-*(原版组件/恢复层)、yc-*(YCode 自有宿主与页面)、恢复家族 cr-*/cb-*/ec-*/sm-*/dc-*、原版 CSS Module 哈希 _name_hash_index 见 1.2;yc-* 选择器 59 个(唯一)
组件实现方式 无组件库:全部是"类名 + 手写 JSX";按钮/输入/弹窗在每个页面各自拼类名 package.json 依赖无 UI kit;wb-button 247 次、wb-input* 多处手拼
无 Tailwind 仓库无 tailwind.config.* / postcss.config.*(仅有 postcss 传递依赖),源码无 @apply 根目录文件列表 + package.json
无 cn / clsx / classnames 依赖 package.json 无该依赖;全仓库唯一的拼接 helper 是 components/ModelSettingsPanel.tsx:41 的 const cx = (name) => prefix + name(前缀 models-settings-panel__),只做加前缀,不做条件合并 代码检索
className 处理 直接字符串字面量或模板字符串拼接(如 className={'a ' + b}、[..].filter(Boolean).join(' '),后者出现在恢复运行时) TSX 全量检索
主题切换 `document.documentElement.dataset.theme = 'light' 'dark',由 src/renderer/src/useSharedTheme.ts 统一写入(localStorage['ycode:theme'],两个窗口共享);组件通过 html[data-theme='dark']` 重映射
恢复模块的并行主题属性 宿主还会在子树上打 `data-cr-theme="dark light"(以及 data-theme),供 [data-cr-theme=dark]` 恢复规则命中
平台/桌面标记 body[data-electron-desktop]、body[data-platform] 由入口写入;恢复 CSS 另有 body.wb-mobile-layout 分支 main.tsx:16-17、settings.tsx:11-12、settings-shell-source.css
字号档位 --yc-font-offset-global 由 fontSize.ts 写入;.cb-font-size-fixed 边界内重解析,防止"双重放大" fontSize.ts、tokens.css 末尾块
恢复文件不可手改 *-source.css / *-recovered.css 带生成头(REA ev id + SHA),由 scripts/rea/recover-*.mjs 生成;页面通过 @import 或 TSX import 引入(例:components/source-home.css:1) 13 个 CSS 带 generated by / Recovered from 头;scripts/rea/ 下 80+ recovery 脚本
打包入口 主窗口与设置窗口共用 window.ycode 假桥(scripts/verify-ui.mjs),命名空间现覆盖 24 个(与渲染进程使用的 24 个一致) 见 5.5

5. 例外与风险

5.1 重复调色板作用域

  • 13 个文件重复定义 --wb-palette-brand-8(含浅色/深色两套),根上没有权威 --wb-palette-*。
  • 组件一旦被移出 .source-* / .models-settings-panel / .yc-capability-center / .chat-pane.cr-theme 等宿主,就会掉色、掉圆角、掉主题。
  • 新组件引用 --wb-* 只有在正确作用域内才成立;引用 --yc-* 才有全局保证(且仍需注意 1.4 的局部重声明)。

5.2 作用域之外的尺寸/图标 token 未定义

  • --wb-size-control-*、--wb-icon-size-* 只在闭包内出现(capability-center-source.css:8、model-settings.css:146、source-styles.css:7 等),排版 token 中引用它们的 --wb-button-height-*、--wb-button-icon-size-* 在根作用域不可解析。

5.3 悬空 token 引用

  • --wb-font-line-height-9(7 个文件引用)与 --wb-font-line-height-6-2(多个恢复文件引用)全仓库无定义;--yc-line-height-6-2: 26px 是同值硬写替代。
  • 影响 --wb-font-spec-h2-line-height、--wb-font-spec-h5-line-height 及部分恢复规则的 line-height 声明(部分浏览器会按 invalid-at-computed-value 处理)。

5.4 加载顺序不是声明顺序

  • 入口先 import App/SettingsWindow、后导入样式,打包后组件自带 CSS 先落地(实测 app-h0tta3aw.css 首条规则来自 source-select-recovered.css)。
  • 结果:styles/app.css、styles/sidebar.css 与恢复层、settings-shell 的相对顺序依赖构建产物,而非源码书写意图。

5.5 scripts/verify-ui.mjs 假桥状态(相对方案文档已变化)

  • 方案文档记录"假桥缺少 window.ycode.library";本次实测该断言已过期:scripts/verify-ui.mjs 的 STUB 现定义 24 个命名空间(window/edit/app/config/general/personalization/agents/memory/models/workspace/session/chat/experts/skills/mcp/projects/automation/library/attachments/speech/git/browser/terminal/resources),与渲染进程实际使用的 24 个一致。
  • 残留风险:假桥是手工维护的 preload 形状副本(无类型约束、返回值多为空集合),新增命名空间后必须同步,否则页面静默半挂载;它只能保证"能挂载",不能保证数据态渲染。
  • 同批新增的静态守护 scripts/check-design-tokens.mjs + scripts/design-token-baseline.json(入口 npm run check:tokens)扫描 src/renderer/src 的裸 hex、裸 px、!important、--wb-* 定义、var(--yc-*)/var(--wb-*) 使用;门禁分类为 core / local / adapter,source / recovered / vendor 只记录不阻塞。本次实测 node scripts/check-design-tokens.mjs --json(334 个文件):ycVarUses 1,372、wbVarUses 22,766、important 926,与本文件第 0 节手工统计完全一致;对比口径时以该 JSON 为准(它按分类拆分,本文件第 5.6 节只列头部文件)。

5.6 !important 与 CRLF

  • !important 总量 926,集中在恢复/投影文件:
文件 数量
projects/source-project-detail-recovered.css 287
projects/source-projects-recovered.css 272
components/workspace-source.css 108
workbuddy/workbench/source-code-assets/editor-gwlzV742.css 97
components/sidebar-shell-source.css 19
capabilities/created-expert-source.css 16
workbuddy/composer/add-menu/source.css、components/source-memory-settings-recovered.css 各 13
components/source-home-recovered.css、workbuddy/user-menu/account-menu-source.css、workbuddy/workbench/panel-motion-source.css 各 11

本次点名的四个核心文件:capabilities/capability-center-source.css 0、components/model-settings.css 3、components/source-home-recovered.css 11、workbuddy/conversation/source-styles.css 3。

  • 换行符:320 个 CSS/TSX/TS 文件为 LF,11 个为 CRLF:capabilities/ExpertsPage.tsx、capabilities/SkillsPage.tsx、components/ChatPane.tsx、components/MessageBubble.tsx、components/model-settings.css、components/ModelSettingsPanel.tsx、components/PersonalizationSettingsPanel.tsx、components/RightSidebar.tsx、components/Sidebar.tsx、workbuddy/conversation/SourceWriteFileView.tsx、workbuddy/conversation/ToolCallRenderer.tsx。跨文件 diff 会整文件抖动。

5.7 深色主题按作用域重写

  • 除了 tokens.css 的 18 条根级重映射,深色还分别写在:model-settings.css:147、source-home-recovered.css:3、source-select-recovered.css:3、source-workspace-picker-recovered.css:3、source-chat-header-recovered.css:3、source-model-picker-recovered.css:3、source-settings-navigation-recovered.css:3、source-general-settings-recovered.css、source-agents-panels-recovered.css:7、source-about-help-panels-recovered.css:4、source-appearance-panel-recovered.css:4、source-memory-settings.css:41、settings-shell-source.css:6、library/library.css:44、projects/project-menu.css:20、automations/automation-page.css:1625,2730、components/app-discover-popover.css:49、workbuddy/workbench/workbench-adapters.css:48-50、workbuddy/subagents/theme.css 等,且部分恢复规则同时识别 body.dark / body.vscode-dark / .vscode-dark。
  • 风险:主题值多份拷贝,任一处漏改会出现"局部亮块"。

5.8 已知组件层重复

  • 按钮 3 套(wb-button / .btn+.btn-icon / .automation-button),输入框 ≥4 套,弹窗 2 套(wb-modal / .dialog),提示 4 套(model-ui-toast / yc-skill-notice / yc-member-notice / .notice),空态每页一套,骨架 4 套,图标 25 个模块 + 95 处散落内联 SVG(164 − 69,见 3.3)。

6. 目标层(指向方案,不在此展开)

目标架构、兼容层桥接规则、组件抽取优先级(Button/Input/Select/Dialog/Popover/Tabs → Checkbox/Switch/Card/ListItem/Badge/EmptyState → Avatar/Spinner/Tooltip/Toast)与 P0→P4 迁移顺序,全部以 docs/设计系统提取与统一方案-2026-10-18.md 为准。组件接口契约(命名规范、变体矩阵、禁止事项)以同批产出的 docs/界面基础组件规范-2026-10-18.md 为准(如该文件存在);本文件第 5.5 节已回填 P0 两项工具的当前实测状态(npm run check:tokens 静态守护、修正后的 scripts/verify-ui.mjs 假桥),后续 Build / Audit 以这两个入口 + 本文件第 2 节取值为改动前后的基线。

附录:复核命令

# 权威层与声明数
rg -c -- "--yc-[a-z0-9-]+\s*:" src/renderer/src/styles/tokens.css
rg -c -- "--wb-[a-z0-9-]+\s*:" src/renderer/src/workbuddy/typography/tokens.css

# 作用域重复调色板
rg -l -- "--wb-palette-brand-8:" src/renderer/src

# 悬空 token
rg -l -- "var\(--wb-font-line-height-9\)|var\(--wb-font-line-height-6-2\)" src/renderer/src
rg -n -- "--wb-font-line-height-(9|6-2):" src/renderer/src

# 加载顺序(源码)
Select-String -Path src/renderer/src/main.tsx,src/renderer/src/settings.tsx -Pattern "import '.+\.css'"

# 加载顺序(产物)
Select-String -Path out/renderer/index.html -Pattern '\.css'

# 假桥覆盖面
rg -o -- "window\.ycode\.[a-zA-Z]+" src/renderer/src --glob "*.tsx" --glob "*.ts" | Sort-Object -Unique

# !important / CRLF 抽查
rg -o -F "!important" src/renderer/src --glob "*.css" | Measure-Object