132 lines
11 KiB
Markdown
132 lines
11 KiB
Markdown
# WorkBuddy 对话区前端布局实测
|
||
|
||
> 2026-10-08补充:[最新原生内层文字与布局审计](ygent-workbuddy-render-audit-2026-10-08.md)。下文外层用户气泡13px、输入容器14px不是实际文字字号;本机Slate内层两处实际均15px,应以最新审计为准。
|
||
|
||
验证对象:WorkBuddy AI 5.7.6、Windows、主窗口 1200 × 762 CSS px、DPR 1。
|
||
证据来自真实页面 CDP computed style、元素矩形、内联样式及安装包 CSS。
|
||
这是一个窗口与会话下的实测,不代表所有分辨率和用户字号设置。
|
||
|
||
## 字体规则
|
||
|
||
对话正文不是每级字号各自写死 `px`。Markdown 先接入根字号和行高 token,再由段落与标题按相对比例排版;运行时显示出来的像素值只是当时 token 的计算结果。输入框属于另一套控件样式,当前 CSS 确实单独声明了 `14px`。
|
||
|
||
| 元素 | 运行时实测 | CSS 规则 |
|
||
|---|---:|---|
|
||
| Markdown 根节点 | 当前解析为 17.143px / 30px | `font-size: var(--cr-md-root)`;行高 `var(--cr-md-line-height, 1.75)` |
|
||
| Markdown 段落 | 当前解析为 15px / 26.25px | `font-size: .875em`,继承 1.75 行高 |
|
||
| Markdown 一级标题 | 由 token 控制 | `font-size: var(--cr-md-h1-font-size, 1.25em)` |
|
||
| Markdown 行内代码 | 按父级字号 | `font-size: 1em` |
|
||
| Markdown 表头 | 当前解析为 15px / 26.25px,字重 600 | 单元格横向 padding 12px;浅色表头实测 `#f7f7f7` |
|
||
| 输入区 | 当前解析为 14px / 21px | `.cr-input-box` 声明 `font-size:14px; line-height:1.5` |
|
||
| 输入编辑器 | 高度 64px,padding 横向 16px | `.cr-input-editor-host` `min-height:64px; overflow-y:auto` |
|
||
|
||
Markdown 组件声明 `--cr-md-root: var(--cb-md-root, 16px)`,当前主题解析为
|
||
`--cb-md-root: 17.143px`。HTML 根字体为 16px,页面 zoom 和 visual viewport scale 均为 1。
|
||
本次 15px 段落是根字号乘 `.875em` 的计算结果,不能反推为源码把段落固定写成 `15px`,
|
||
也不能归因于 viewport 缩放。字号变量的上游已在组件 bundle 中找到,具体的六级调节规则见下节。
|
||
|
||
实际正文段落间距为 12px;代码块实测使用 monospace、12.857px / 22.5px 行高、
|
||
横向 padding 16px,并限制内部滚动。Ygent 当前默认档的 Markdown 根字号、段落比例、
|
||
行高与代码字号已按上述规则设置;用户气泡仍单独采用 13px / 19px。
|
||
|
||
## 全局字号控制
|
||
|
||
`renderer/assets/ui-docs-viewer-veG3wQhz.js` 中有统一的字号级别管理器,作用超过 Markdown:
|
||
正文、标题、说明文字、代码、按钮文字和按钮高度都接入它。
|
||
|
||
级别保存在 `localStorage` 的 `agent-ui-font-size-level:v2`,并同步到
|
||
`config.preference.fontSizeLevel`。有效级别为 1 到 6;没有有效保存值时默认为 2。
|
||
每级同时更新根 Markdown 字号和全局偏移量:
|
||
|
||
| 级别 | 根字号 token `--cb-md-root` | 全局字号偏移 |
|
||
|---:|---:|---:|
|
||
| 1 | 16px | -1px |
|
||
| 2(默认) | 17.143px | 0px |
|
||
| 3 | 18.286px | +1px |
|
||
| 4 | 20.571px | +2px |
|
||
| 5 | 22.857px | +2px |
|
||
| 6 | 26.286px | +2px |
|
||
|
||
`--wb-font-body-size`、`--wb-font-caption-size`、标题和代码等设计 token 用各自的 base size
|
||
加全局偏移计算。全局 token 偏移夹在 -1 至 +2px,避免级别 5、6 把紧凑控件撑大过多;
|
||
按钮高度再按更新后的行高和垂直 padding 重算。
|
||
|
||
旧 CSS 中直接写为 `font-size: 13px` 的规则也会参与字号调节。管理器扫描可读的样式表,
|
||
按级别注入 `max(8px, calc(13px + var(--cb-font-size-offset) * 1px))` 覆盖规则。
|
||
它保留 `@media` 分组,观察后续新增的样式表,并排除 `.cb-font-size-fixed` 及其子孙节点,
|
||
以便明确声明固定字号的控件不随全局级别改变。
|
||
|
||
Windows 上可用 `Ctrl+-` 降一级、`Ctrl++` 升一级、`Ctrl+0` 恢复默认。级别限制在 1 到 6。
|
||
切换时派发 `cb-font-size-change` 和 `cb-font-size-level-change` 事件,让组件刷新。
|
||
源码会同时出现字体 token、相对 `em` 和少量固定 `px`:全局设置更新设计 token,
|
||
并兼容旧组件里的固定字号。
|
||
|
||
## 宽度与主布局
|
||
|
||
在当前 1200px 窗口中,左侧栏为 280px,主内容区为 920px。对话历史和输入区各自在主内容区居中,并使用相同的 832px 上限:
|
||
|
||
- `.cr-message-list__content` 运行时内联 `max-width: 832px`,源码使用 `width:100%; max-width:100%; margin-inline:auto`。
|
||
- 对话内容区左右 padding 为主题变量 `--cr-message-list-content-inline-padding:40px`。832px 外框扣除 80px 后,消息正文列为 752px。
|
||
- 输入区外框上限同为 832px,外框左右各 padding 24px,输入控件宽度为 784px。
|
||
- 小于 832px 的可用主列时,`width:100%` 收缩外框,正文与输入仍分别保留自己的横向 padding。布局跟随内容区宽度,不依靠 viewport 单位设定字体。
|
||
- 对话主列是 flex 布局。消息列表 `flex:1; min-height:0; overflow-y:auto`,输入区 `flex-shrink:0` 固定在底部;这样滚动发生在历史列表内部,长内容不会把输入区挤出窗口。
|
||
- 输入编辑区设置最小高度,并通过纵向滚动承载增长内容;工具栏单独 flex 布局、`flex-shrink:0`,操作项不会跟着编辑内容收缩。
|
||
|
||
Ygent 对应使用同一内容列:在 1200 × 762 窗口、280px 侧栏和 10px 消息滚动条下,832px 对话外框居中后,消息正文列落在 `x=359..1111`(752px)。助手头像行、回答正文和用户气泡均对齐这条列;输入框外框落在 `x=348..1132`(784px),其编辑器和工具栏分别保留 64px 与 56px 高度。窗口窄于内容上限时,消息列跟随可用宽度收缩,窄屏左右内边距为 16px。
|
||
|
||
实测 DOM 层级中,对话列和输入区都受 832px 居中容器约束,但消息、输入和工具栏是独立组件。这个边界让两边 padding 与窄窗收缩策略各自清晰。
|
||
|
||
## 响应策略
|
||
|
||
- 主列采用 `width:100% + max-width + margin:auto`;用可用宽度与最大宽度自然收缩。
|
||
- `.cr-message-list` 声明 `container-type:inline-size`,具备查询容器的能力。当前对应 CSS 文件没有 `@container` 规则,不能仅凭声明推断对话区已有完整的容器断点体系。
|
||
- 对话输入工具栏有 `width <= 320px` 的局部断点,在极窄宽度下隐藏次要 context-usage 标记,给常用操作留空间。
|
||
- 主内容 CSS 的另一个欢迎页容器 `.chat-container--welcome` 默认上限 848px,在 viewport 至少 1681px 时扩到 1008px;这是不同容器的规则,不能跟本次运行页面的 832px 对话列混为一谈。
|
||
- 组件 CSS 使用 `prefers-reduced-motion` 减少消息列表进出动画。
|
||
|
||
## 消息气泡、widget 与输入区
|
||
|
||
同一窗口的当前会话快照实测:
|
||
|
||
| 元素 | 运行时规格 |
|
||
|---|---|
|
||
| 助手头部 `.cr-agent__header` | 752px 内容宽;24.5px 高;24px 圆形标识、10px 间距;名称 14px / 24.5px、字重 600;下方间距 12px |
|
||
| 完成状态 `.cr-collapse__header` | 文案 `已完成 3m2s`;15px / 26.25px、三级文字色、宽度随内容;12px 箭头与 8px 间距 |
|
||
| Markdown 根 `.cr-markdown` | 字号 17.143px / 行高 30.0002px(当前 2 级);段落按 `.875em`,实测 15.0001px / 26.2502px |
|
||
| 列表 `.cr-markdown ul` | 15.0001px / 26.2502px;左缩进 21.4502px;列表后间距 16px;列表项间距 4px |
|
||
| 表格单元格 `.cr-markdown th/td` | 15.0001px / 26.2502px;padding `8px 12px`;表头底色 `#f7f7f7` |
|
||
| 代码块 `.cr-markdown pre` | 12.8573px / 22.5002px;padding `12px 16px` |
|
||
| 用户气泡 `.cr-self-bubble` | 13px / 19px;`#f2f2f2`;padding `8px 12px`;圆角 `16px 16px 0`;最小宽 40px、最大宽 100%、最大高 310px,内部滚动 |
|
||
| 用户消息工具栏 `.cr-toolbar` | 相对用户气泡框架绝对定位在底部;默认透明;时间 14px / 20px,含复制和编辑按钮 |
|
||
| 表格操作 `.cr-message-quote-table-menu` | hover 时显示于表格右上角;菜单 116×38px,按钮 106×28px;点击把原表格 Markdown 加入输入草稿 |
|
||
| widget 卡 `.cr-widget-card` | 正文列宽 752px;边框 `1px solid #ebebeb`、圆角 16px、纵向 margin 8px |
|
||
| widget 内容 `.cr-widget-body` | padding `12px 16px`;当前 iframe 宽 718px,高度随内容变化 |
|
||
| widget iframe | `sandbox="allow-scripts"`,不含 `allow-same-origin`;CSP 允许内联脚本与指定 CDN |
|
||
| 输入容器 `.cr-input-container` | `x=348, y=592, 784×134px`;白底、`1px solid #e6e6e6`、24px 圆角、两层轻阴影 |
|
||
| 输入编辑区 `.cr-input-editor-host` | `x=349, y=605, 782×64px`;横向 padding 16px;字号 14px / 21px |
|
||
| 输入工具栏 `.cr-input-toolbar` | `x=349, y=669, 782×56px`;padding 12px;按钮 32px |
|
||
| 禁用发送按钮 | 32px 圆形;图标圆底填充 `rgba(0,0,0,.2)` |
|
||
|
||
widget 的高度由 iframe 内容决定。SVG 根据自身 viewBox 呈现比例,HTML 图表按内部容器高度扩展;iframe 向父层报告尺寸,宿主验证来源并限制最大值。
|
||
|
||
## 对 Ygent 的参考价值
|
||
|
||
1. 给对话消息和输入区一个共享的居中最大宽度,再分别配置内边距。避免消息列与输入框在宽屏各自漂移。
|
||
2. 用 `min-width:0`、`min-height:0`、flex shrink 和列表内部 `overflow-y:auto` 明确滚动容器。窄窗或长内容时,输入区仍留在底部。
|
||
3. 把 Markdown 基准、段落倍率、行高、输入区字号做成角色明确的 token。Ygent 的默认 Markdown 规则与本次实测一致;用户气泡和输入区按各自控件规格管理。全局字号应明确级别、上下界、持久化、组件更新方式及固定字号例外。Ygent 六档根字号跟随 WorkBuddy,常规控件偏移在第 5、6 档封顶为 +2px。
|
||
4. 在真正受限的控件上做局部响应。窄宽时优先收起次要工具标记,别先整体缩小所有字号。
|
||
5. 以运行时 computed style 验收主题变量、Electron zoom 和实际像素;只读静态 CSS 很容易漏掉主题宿主注入的 token。computed `px` 是实测结果,不是 token 定义本身。
|
||
|
||
## 证据与局限
|
||
|
||
- 运行时快照与截图保存在用户私有目录 `%USERPROFILE%/.ygent/imports/workbuddy-debug-20261008/`,不放进仓库。
|
||
- 主要组件 CSS:`renderer/assets/lib-chat-ui-B-axvvx6.css`。
|
||
- 字号管理器:`ui-docs-viewer-veG3wQhz.js`,包括级别表、存储键、快捷键和旧式 `px` 样式覆盖。
|
||
- 正文段落规则:`.cr-markdown` 使用主题根字号和 1.75 行高,`.cr-markdown p` 使用 `.875em`,标题也使用相对字号 token。
|
||
- 输入布局规则:`.cr-input-box` 14px / 1.5;编辑器最小高 64px;输入容器运行时 inline `min-height:96px`。
|
||
- 当前会话主体宽度 832px 来自运行时 inline style;CSS 文件里 `.cr-message-list__content` 只声明 `max-width:100%`。具体控制该 inline 值的组件逻辑尚未追踪。
|
||
- DOM 是虚拟列表,仅包含当前已挂载部分。离开视口的消息矩形可以是负坐标,不能按快照节点数估算完整会话。
|
||
- 点击窗口不同宽度进行重复采样前,先另建输出目录。复测时同时记录 viewport、DPR、Electron zoom、主题与相关主题变量。
|
||
|
||
采集过程见 [运行时调试 SOP](workbuddy-cdp.md),可续接会话数据见 [对话导入说明](workbuddy-reference-import.md)。
|