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.
43 KiB
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里。
冲突点清单:
- 声明顺序 ≠ 生效顺序:
main.tsx的import App/import { SettingsWindow }写在样式导入之前,打包后组件自带 CSS 先于入口样式落地。 - 同特异性并列时由后加载者获胜(本地
.btn与恢复wb-button在同一元素上并用时需要显式顺序,styles/app.css与sidebar-shell-source.css都定义过按钮外观)。 - 作用域闭包不可迁移:把元素移出
.source-home/.models-settings-panel/.chat-pane.cr-theme等宿主后,--wb-*立即失配。 - 深色主题按作用域各写一遍:
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 个文件):ycVarUses1,372、wbVarUses22,766、important926,与本文件第 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