diff --git a/.agents/notes/implemented/feature/2026-08-18-settings-font-size-control.i18n.yaml b/.agents/notes/implemented/feature/2026-08-18-settings-font-size-control.i18n.yaml index 53ae33271d..f0999e1aa3 100644 --- a/.agents/notes/implemented/feature/2026-08-18-settings-font-size-control.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-08-18-settings-font-size-control.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write .agents/notes/implemented/feature/2026-08-18-settings-font-size-control.md -2026-08-18-settings-font-size-control.md: 34ee7f28f58a0a5a5dc8cd39bc4cecf5e081359f -2026-08-18-settings-font-size-control.zh.md: 2c2ea714d50ca1f934d78ede6175935338488331 +2026-08-18-settings-font-size-control.md: 778893a2c0943f1d3af8905a27efb526071e073b +2026-08-18-settings-font-size-control.zh.md: 71ff3b556622e7091891f8e18f5eefcbda2b0851 diff --git a/.agents/notes/implemented/feature/2026-08-18-settings-font-size-control.md b/.agents/notes/implemented/feature/2026-08-18-settings-font-size-control.md index 34ee7f28f5..778893a2c0 100644 --- a/.agents/notes/implemented/feature/2026-08-18-settings-font-size-control.md +++ b/.agents/notes/implemented/feature/2026-08-18-settings-font-size-control.md @@ -14,7 +14,7 @@ The conversation's body text size was fixed (14px after the 0.875 markdown-ladde **Presentation rides the existing snapshot pipeline.** The service never touches the DOM: ui-layout's `ThemePresenter` writes `--dsh-content-font-size` on `body` from each snapshot (and retracts it on dispose), and the Host boot script embeds the durable value in the index response so first paint uses the chosen size — the same pre-plugin path the dark-mode attribute takes, avoiding a font-size flash. -**One CSS delta variable moves the ladder.** `gradient-shadow-text.css` derives `--dsh-content-font-delta: calc(var(--dsh-content-font-size, 14px) - 14px)` and shifts the markdown h1–h4 and base variants (size and line height) by that same px increment, preserving the heading hierarchy and each variant's leading. Table, small, and code variants stay fixed — as does the interrupted-turn `.stopped` tag (11px): they are dense secondary text whose defaults would fall below legibility when stepped down. Consumers outside the token ladder read `var(--dsh-content-font-size, 14px)` (or `calc( + var(--dsh-content-font-delta, 0px))` for smaller steps) and `calc( + var(--dsh-content-font-delta, 0px))` directly: the assistant narration root, the user bubble (reference summaries and their inline glyphs included), the composer card (whose textarea/mirror/backdrop stack inherits font metrics from the card by design), and the flow chrome around them — the shared DisclosureRow header (tool calls, think, commands; row height, title, and leading box all move) with its expanded bodies' `22px + delta` indent keeping content aligned under the shifted title start, ToolRow/bash-row summaries and file links, think text (12px keeping its 2px step under the body), compaction/context/retry/error rows, StatsLine, the chat hint and open-error strips, the workflow-run panel (run/phase headers and expanded member rows), the message clock and icon actions (slot-injected message-feedback actions match through the same variables), and the turn status line. Flow icons scale through each leading box's CSS edge (`svg` width/height overriding the glyph attributes); StateDot is exempt via its `data-state` attribute — a status mark, not text furniture. The 14px fallbacks keep every surface pixel-identical when the variable is absent (tests, storybook-like mounts, remote compositions before adoption). +**One CSS delta variable moves the ladder, plus a derived secondary tier.** `gradient-shadow-text.css` derives `--dsh-content-font-delta: calc(var(--dsh-content-font-size, 14px) - 14px)` and shifts the markdown h1–h4 and base variants (size and line height) by that same px increment, preserving the heading hierarchy and each variant's leading. Secondary-tier text — one step under the body — reads `--dsh-content-font-size-secondary: min(setting − 1px, max(13px, setting − 2px))`: setting −1 at ≤14, setting −2 above (12→11, 13→12, 14→13, 15→13, 16→14, 17→15), with `--dsh-content-font-delta-secondary` (secondary − 13px) moving its line heights. The secondary tier covers the markdown table variants, the shared DisclosureRow title (tool calls, think, commands), ToolRow/bash-row summaries and file links, think text, compaction/context/retry/error rows, StatsLine, the chat hint and open-error strips, the workflow-run panel headers/counts/statuses, the turn-status clock, reference summaries, and the note-trigger label. Small and code variants stay fixed — as does the interrupted-turn `.stopped` tag (11px): they are dense secondary text whose defaults would fall below legibility when stepped down. Consumers outside the token ladder at the body size read `var(--dsh-content-font-size, 14px)` and `calc( + var(--dsh-content-font-delta, 0px))` directly: the assistant narration root, the user bubble (inline reference glyphs included), the composer card (whose textarea/mirror/backdrop stack inherits font metrics from the card by design), the compaction/DisclosureRow geometry (row height, leading box, expanded bodies' `22px + delta` indent), the message clock and icon actions (slot-injected message-feedback actions match through the same variables), and the turn status line. Flow icons scale through each leading box's CSS edge (`svg` width/height overriding the glyph attributes); StateDot is exempt via its `data-state` attribute — a status mark, not text furniture. The fallbacks (14px body, 13px secondary) keep every surface pixel-identical when the variables are absent (tests, storybook-like mounts, remote compositions before adoption). **The stepper is a pill, not a menu.** The row reuses the selector-pill geometry (h36 r18 module fill) with the value centered in the pill, the up/down arrow column revealed on hover/focus-within and absolutely anchored to the pill's right edge (so revealing never moves the value), and a `px` unit label after the pill. A tertiary description line under the title states the scope — the size only affects conversation content, not the application chrome. Arrows disable at the bounds; the display follows the store mirror, never the click echo — the same store/face pattern as the Appearance row. @@ -24,8 +24,8 @@ The conversation's body text size was fixed (14px after the 0.875 markdown-ladde **Scaling via a multiplier (`em`/percentage) instead of a px delta.** Rejected: multiplying spreads the 12–17px range disproportionately across the ladder (21px h1 would swing ~18–25.5px) and produces fractional line heights; the fixed px shift keeps every step integer and the hierarchy's px gaps intact. -**Scaling every font token (tables, code, small).** Rejected: those variants are secondary/dense by design; at −2 the small ladder would hit 10px and code 9px, below legibility. +**Scaling every font token (small, code).** Rejected: those variants are dense by design; at −2 the small ladder would hit 10px and code 9px, below legibility. The table variants instead join the secondary tier, bottoming out at 11px at the 12px setting — the same size think text reaches there. ## Consequences -The 0.875 markdown-ladder rescale (body 16 → 14) ships with this change as the new default rendering; at delta 0 every axis consumer is pixel-identical to that rescaled baseline, and surfaces without the variable fall back to the same 14px. A changed size persists in `$DSH_HOME/settings.yaml`, survives reloads without flashing (the boot script writes the durable value pre-hydration and `ThemeRuntime` seeds its initial snapshot from it), applies live across transcript and composer, and remote browsers keep the process-local-selection rule the theme preference already has. `setFontSize` joins the model-visible cordis client API catalog beside `setTheme`. +The 0.875 markdown-ladder rescale (body 16 → 14) ships with this change as the new default rendering; at the default setting the body-size consumers match that rescaled baseline, and the secondary tier renders at 13px (one step down — a deliberate demotion of the flow-row titles and summaries that previously sat at the body size). Surfaces without the variables fall back to the same defaults. A changed size persists in `$DSH_HOME/settings.yaml`, survives reloads without flashing (the boot script writes the durable value pre-hydration and `ThemeRuntime` seeds its initial snapshot from it), applies live across transcript and composer, and remote browsers keep the process-local-selection rule the theme preference already has. `setFontSize` joins the model-visible cordis client API catalog beside `setTheme`. diff --git a/.agents/notes/implemented/feature/2026-08-18-settings-font-size-control.zh.md b/.agents/notes/implemented/feature/2026-08-18-settings-font-size-control.zh.md index 2c2ea714d5..71ff3b5566 100644 --- a/.agents/notes/implemented/feature/2026-08-18-settings-font-size-control.zh.md +++ b/.agents/notes/implemented/feature/2026-08-18-settings-font-size-control.zh.md @@ -14,7 +14,7 @@ **呈现走既有快照管线。**服务绝不接触 DOM:ui-layout 的 `ThemePresenter` 依据每份快照在 `body` 上写 `--dsh-content-font-size`(dispose 时收回),Host 引导脚本把持久化值嵌入 index 响应,让首帧就使用所选字号——与暗色属性同一条插件前路径,避免字号闪变。 -**一个 CSS 增量变量平移阶梯。**`gradient-shadow-text.css` 派生 `--dsh-content-font-delta: calc(var(--dsh-content-font-size, 14px) - 14px)`,把 markdown h1–h4 与 base 各变体(字号与行高)按同一像素增量平移,保持标题层级与各变体的行距。表格、small 与 code 变体保持固定——中断回合的 `.stopped` 标签(11px)同样固定:它们是密集次级文本,其默认值在字号下调时会低于可读下限。token 阶梯之外的消费方直接读取 `var(--dsh-content-font-size, 14px)`(较小档位则用 `calc(<自身默认> + var(--dsh-content-font-delta, 0px))`)与 `calc(<默认行高> + var(--dsh-content-font-delta, 0px))`:助手正文根节点、用户气泡(含引用摘要及其行内字形)、composer 卡片(其 textarea/mirror/backdrop 三层按设计从卡片继承字体度量),以及围绕它们的流内 chrome——共享的 DisclosureRow 头部(工具调用、think、命令;行高、标题与 leading 盒同步移动),其展开内容以 `22px + delta` 缩进跟随平移后的标题起点保持对齐、ToolRow/bash 行的 summary 与文件链接、think 正文(12px,保持比正文小 2px 的层级)、compaction/context/retry/错误行、StatsLine、chat 提示与打开失败条、workflow-run 面板(run/phase 头部与展开的成员行)、消息时钟与图标操作(slot 注入的消息反馈操作经同一对变量同步缩放),以及回合状态行。流内图标经由各 leading 盒的 CSS 边长缩放(`svg` width/height 覆盖字形自身属性);StateDot 通过其 `data-state` 属性豁免——它是状态标记,不是文字组件。14px 回退让变量缺席时(测试、独立挂载、采纳前的远程组合)所有表面逐像素不变。 +**一个 CSS 增量变量平移阶梯,另派生一个低一档层级。**`gradient-shadow-text.css` 派生 `--dsh-content-font-delta: calc(var(--dsh-content-font-size, 14px) - 14px)`,把 markdown h1–h4 与 base 各变体(字号与行高)按同一像素增量平移,保持标题层级与各变体的行距。低一档文本——比正文低一档——读 `--dsh-content-font-size-secondary: min(设置值 − 1px, max(13px, 设置值 − 2px))`:设置 ≤14 时为设置值 −1,>14 时为设置值 −2(12→11、13→12、14→13、15→13、16→14、17→15),其行高经 `--dsh-content-font-delta-secondary`(低一档值 − 13px)随动。低一档覆盖:markdown 表格变体、共享 DisclosureRow 标题(工具调用、think、命令)、ToolRow/bash 行的 summary 与文件链接、think 正文、compaction/context/retry/错误行、StatsLine、chat 提示与打开失败条、workflow-run 面板的头部/计数/状态、回合状态时钟、引用摘要与笔记触发标签。small 与 code 变体保持固定——中断回合的 `.stopped` 标签(11px)同样固定:它们是密集次级文本,其默认值在字号下调时会低于可读下限。token 阶梯之外按正文档读取的消费方直接使用 `var(--dsh-content-font-size, 14px)` 与 `calc(<默认行高> + var(--dsh-content-font-delta, 0px))`:助手正文根节点、用户气泡(含行内引用字形)、composer 卡片(其 textarea/mirror/backdrop 三层按设计从卡片继承字体度量)、compaction/DisclosureRow 的行几何(行高、leading 盒、展开内容的 `22px + delta` 缩进)、消息时钟与图标操作(slot 注入的消息反馈操作经同一对变量同步缩放),以及回合状态行。流内图标经由各 leading 盒的 CSS 边长缩放(`svg` width/height 覆盖字形自身属性);StateDot 通过其 `data-state` 属性豁免——它是状态标记,不是文字组件。回退值(正文 14px、低一档 13px)让变量缺席时(测试、独立挂载、采纳前的远程组合)所有表面逐像素不变。 **步进器是药丸控件,不是菜单。**该行复用选择器药丸几何(h36 r18 模块填充),数值在药丸内居中,上下箭头列在 hover/focus-within 时显示并绝对定位在药丸右缘(显示时数值不移动),药丸后带 `px` 单位标签。标题下方的三级说明行标明作用范围——字号仅影响会话内容,不影响应用外框。到达边界时对应箭头禁用;显示跟随 store 镜像,绝不跟随点击回声——与外观行相同的 store/face 模式。 @@ -24,8 +24,8 @@ **用倍率(`em`/百分比)而非像素增量缩放。**否决:乘法会让 12–17px 的范围在阶梯上不成比例地放大(21px 的 h1 会摆动到约 18–25.5px),并产生小数行高;固定像素平移让每一档都是整数,层级间的像素差保持不变。 -**缩放全部字体 token(表格、code、small)。**否决:这些变体按设计就是次级/密集文本;−2 档时 small 阶梯会降到 10px、code 降到 9px,低于可读下限。 +**缩放全部字体 token(code、small)。**否决:这些变体按设计就是密集文本;−2 档时 small 阶梯会降到 10px、code 降到 9px,低于可读下限。表格变体改为并入低一档层级,在 12px 设置下触底 11px——与 think 文本在该设置下相同。 ## 后果 -0.875 的 markdown 阶梯重缩放(正文 16 → 14)作为新的默认渲染随本变更一同交付;增量为 0 时所有轴消费方与该重缩放基线逐像素一致,无变量的表面回退到同样的 14px。修改后的字号持久化在 `$DSH_HOME/settings.yaml`,重载不闪变(引导脚本在 hydration 前写入持久化值,`ThemeRuntime` 以它为初始快照种子),在转录与 composer 上实时生效;远程浏览器沿用主题偏好既有的进程内选择规则。`setFontSize` 与 `setTheme` 一同进入模型可见的 cordis 客户端 API 目录。 +0.875 的 markdown 阶梯重缩放(正文 16 → 14)作为新的默认渲染随本变更一同交付;默认设置下正文档消费方与该重缩放基线一致,低一档渲染为 13px(低一步——这是对此前按正文档渲染的流内行标题与摘要的有意降档)。无变量的表面回退到同样的默认值。修改后的字号持久化在 `$DSH_HOME/settings.yaml`,重载不闪变(引导脚本在 hydration 前写入持久化值,`ThemeRuntime` 以它为初始快照种子),在转录与 composer 上实时生效;远程浏览器沿用主题偏好既有的进程内选择规则。`setFontSize` 与 `setTheme` 一同进入模型可见的 cordis 客户端 API 目录。 diff --git a/apps/web/tests/settings-chrome.e2e.ts b/apps/web/tests/settings-chrome.e2e.ts index b36508aa5e..425ff5d1ee 100644 --- a/apps/web/tests/settings-chrome.e2e.ts +++ b/apps/web/tests/settings-chrome.e2e.ts @@ -351,7 +351,19 @@ describe('web e2e: settings modal and General preferences', () => { const readFontSize = async (target: Page = page): Promise => await target.evaluate( () => document.body.style.getPropertyValue('--dsh-content-font-size'), ) + // The secondary tier resolved by the real engine: a probe element's + // font-size forces min/max/calc evaluation, which the CSS-text specs + // cannot exercise. Setting −1 at ≤14, setting −2 above. + const readSecondaryFontSize = async (): Promise => await page.evaluate(() => { + const probe = document.createElement('div') + probe.style.fontSize = 'var(--dsh-content-font-size-secondary, 13px)' + document.body.appendChild(probe) + const size = getComputedStyle(probe).fontSize + probe.remove() + return size + }) expect(await readFontSize()).toBe('14px') + expect(await readSecondaryFontSize()).toBe('13px') await page.getByRole('button', { name: '设置', exact: true }).click() const dialog = page.getByRole('dialog', { name: '设置' }) await dialog.waitFor({ timeout: 10_000 }) @@ -360,9 +372,13 @@ describe('web e2e: settings modal and General preferences', () => { const increase = dialog.getByRole('button', { name: '增大字号' }) await increase.click() await dialog.getByText('15', { exact: true }).waitFor({ timeout: 5_000 }) + // 15 is the piecewise boundary: the secondary tier holds at 13px (−2) + // where the ≤14 branch would have given 14px (−1). + await expect.poll(readSecondaryFontSize, { timeout: 5_000 }).toBe('13px') await increase.click() await dialog.getByText('16', { exact: true }).waitFor({ timeout: 5_000 }) await expect.poll(readFontSize, { timeout: 5_000 }).toBe('16px') + await expect.poll(readSecondaryFontSize, { timeout: 5_000 }).toBe('14px') await expect.poll(async () => readFile(join(scaffold.harnessHome, 'settings.yaml'), 'utf8'), { timeout: 5_000 }) .toMatch(/ui-theme:\n(?:\s+\w+: .*\n)*?\s+fontSize: 16/) await page.keyboard.press('Escape') @@ -375,6 +391,7 @@ describe('web e2e: settings modal and General preferences', () => { acknowledgeReloadConnectionLoss(tripwire, warningStart) await page.waitForSelector('[class*="frame"]', { timeout: 30_000 }) await expect.poll(readFontSize, { timeout: 5_000 }).toBe('16px') + expect(await readSecondaryFontSize()).toBe('14px') // Restore the default for the specs that follow (and the dialog golden). await page.getByRole('button', { name: '设置', exact: true }).click() diff --git a/packages/client/ui-chat/src/client/chat/ChatView.module.css b/packages/client/ui-chat/src/client/chat/ChatView.module.css index f2f5a3a908..502ae295be 100644 --- a/packages/client/ui-chat/src/client/chat/ChatView.module.css +++ b/packages/client/ui-chat/src/client/chat/ChatView.module.css @@ -101,8 +101,8 @@ .turnStatusClock { margin-left: 8px; font: var(--dsw-font-xs-13); - font-size: calc(13px + var(--dsh-content-font-delta, 0px)); - line-height: calc(20px + var(--dsh-content-font-delta, 0px)); + font-size: var(--dsh-content-font-size-secondary, 13px); + line-height: calc(20px + var(--dsh-content-font-delta-secondary, 0px)); font-weight: 400; font-variant-numeric: tabular-nums; color: var(--dsw-alias-label-caption); @@ -125,14 +125,14 @@ .hint { color: var(--dsw-alias-label-tertiary); - font-size: calc(12px + var(--dsh-content-font-delta, 0px)); - line-height: calc(18px + var(--dsh-content-font-delta, 0px)); + font-size: var(--dsh-content-font-size-secondary, 13px); + line-height: calc(18px + var(--dsh-content-font-delta-secondary, 0px)); } .openError { color: var(--dsw-alias-state-error-primary); - font-size: calc(12px + var(--dsh-content-font-delta, 0px)); - line-height: calc(18px + var(--dsh-content-font-delta, 0px)); + font-size: var(--dsh-content-font-size-secondary, 13px); + line-height: calc(18px + var(--dsh-content-font-delta-secondary, 0px)); } .older { diff --git a/packages/client/ui-chat/src/client/chat/ContextInjectionRow.module.css b/packages/client/ui-chat/src/client/chat/ContextInjectionRow.module.css index e9173a078d..788322535c 100644 --- a/packages/client/ui-chat/src/client/chat/ContextInjectionRow.module.css +++ b/packages/client/ui-chat/src/client/chat/ContextInjectionRow.module.css @@ -29,7 +29,7 @@ min-width: 0; overflow: hidden; color: var(--dsw-alias-label-tertiary); - font-size: var(--dsh-content-font-size, 14px); + font-size: var(--dsh-content-font-size-secondary, 13px); line-height: calc(24px + var(--dsh-content-font-delta, 0px)); text-overflow: ellipsis; white-space: nowrap; @@ -41,7 +41,7 @@ min-width: 0; overflow: hidden; color: var(--dsw-alias-label-tertiary); - font-size: var(--dsh-content-font-size, 14px); + font-size: var(--dsh-content-font-size-secondary, 13px); line-height: calc(24px + var(--dsh-content-font-delta, 0px)); text-overflow: ellipsis; white-space: nowrap; diff --git a/packages/client/ui-chat/src/client/chat/GenericCommandCard.module.css b/packages/client/ui-chat/src/client/chat/GenericCommandCard.module.css index 075029de01..49297685ae 100644 --- a/packages/client/ui-chat/src/client/chat/GenericCommandCard.module.css +++ b/packages/client/ui-chat/src/client/chat/GenericCommandCard.module.css @@ -55,7 +55,7 @@ overflow: hidden; flex: 1 1 auto; color: var(--dsw-alias-label-tertiary); - font-size: var(--dsh-content-font-size, 14px); + font-size: var(--dsh-content-font-size-secondary, 13px); line-height: calc(24px + var(--dsh-content-font-delta, 0px)); text-overflow: ellipsis; white-space: nowrap; diff --git a/packages/client/ui-chat/src/client/chat/MessageItem.module.css b/packages/client/ui-chat/src/client/chat/MessageItem.module.css index ff47ae7717..7cdb951e01 100644 --- a/packages/client/ui-chat/src/client/chat/MessageItem.module.css +++ b/packages/client/ui-chat/src/client/chat/MessageItem.module.css @@ -42,8 +42,8 @@ .referenceSummary { color: var(--dsw-alias-label-tertiary); - font-size: calc(12px + var(--dsh-content-font-delta, 0px)); - line-height: calc(18px + var(--dsh-content-font-delta, 0px)); + font-size: var(--dsh-content-font-size-secondary, 13px); + line-height: calc(18px + var(--dsh-content-font-delta-secondary, 0px)); } .contextRow { padding: 2px 0; @@ -120,7 +120,7 @@ .compactionTitle { flex: none; - font-size: var(--dsh-content-font-size, 14px); + font-size: var(--dsh-content-font-size-secondary, 13px); line-height: calc(24px + var(--dsh-content-font-delta, 0px)); color: var(--dsw-alias-label-primary-dimmed); } @@ -139,7 +139,7 @@ min-width: 0; overflow: hidden; color: var(--dsw-alias-label-tertiary); - font-size: var(--dsh-content-font-size, 14px); + font-size: var(--dsh-content-font-size-secondary, 13px); line-height: calc(24px + var(--dsh-content-font-delta, 0px)); text-overflow: ellipsis; white-space: nowrap; @@ -149,14 +149,14 @@ /* Indent under the title, which starts at leading (16 + delta) + gap 6. */ padding: 4px 0 4px calc(22px + var(--dsh-content-font-delta, 0px)); color: var(--dsw-alias-label-tertiary); - font-size: var(--dsh-content-font-size, 14px); + font-size: var(--dsh-content-font-size-secondary, 13px); line-height: calc(24px + var(--dsh-content-font-delta, 0px)); } .retryRow { color: var(--dsw-alias-label-tertiary); - font-size: calc(13px + var(--dsh-content-font-delta, 0px)); - line-height: calc(20px + var(--dsh-content-font-delta, 0px)); + font-size: var(--dsh-content-font-size-secondary, 13px); + line-height: calc(20px + var(--dsh-content-font-delta-secondary, 0px)); } .retrySummary { @@ -227,8 +227,8 @@ margin-top: 3px; padding-left: 14px; overflow-wrap: anywhere; - font-size: calc(12px + var(--dsh-content-font-delta, 0px)); - line-height: calc(18px + var(--dsh-content-font-delta, 0px)); + font-size: var(--dsh-content-font-size-secondary, 13px); + line-height: calc(18px + var(--dsh-content-font-delta-secondary, 0px)); } .retryDetailLabel { @@ -241,8 +241,8 @@ gap: 8px; align-items: start; padding: 2px 0; - font-size: calc(13px + var(--dsh-content-font-delta, 0px)); - line-height: calc(20px + var(--dsh-content-font-delta, 0px)); + font-size: var(--dsh-content-font-size-secondary, 13px); + line-height: calc(20px + var(--dsh-content-font-delta-secondary, 0px)); } .turnErrorDot { diff --git a/packages/client/ui-chat/src/client/chat/ReasoningRow.module.css b/packages/client/ui-chat/src/client/chat/ReasoningRow.module.css index 67cfbf737a..2d7cbe8f07 100644 --- a/packages/client/ui-chat/src/client/chat/ReasoningRow.module.css +++ b/packages/client/ui-chat/src/client/chat/ReasoningRow.module.css @@ -50,15 +50,16 @@ background: var(--dsw-alias-label-caption); } -/* Think text sits one 2px step under the body size and follows the Settings - font-size preference through the same px delta, keeping the step. */ +/* Think text reads the secondary tier — one step under the body size + (setting −1 at ≤14, setting −2 above), shared with every flow-row title + and summary. */ .summary { min-width: 0; overflow: hidden; flex: 1 1 auto; color: var(--dsw-alias-label-tertiary); - font-size: calc(12px + var(--dsh-content-font-delta, 0px)); - line-height: calc(20px + var(--dsh-content-font-delta, 0px)); + font-size: var(--dsh-content-font-size-secondary, 13px); + line-height: calc(20px + var(--dsh-content-font-delta-secondary, 0px)); text-overflow: ellipsis; white-space: nowrap; } @@ -71,8 +72,8 @@ /* Indent under the title, which starts at leading (16 + delta) + gap 6. */ padding: 4px 0 4px calc(22px + var(--dsh-content-font-delta, 0px)); color: var(--dsw-alias-label-tertiary); - font-size: calc(12px + var(--dsh-content-font-delta, 0px)); - line-height: calc(20px + var(--dsh-content-font-delta, 0px)); + font-size: var(--dsh-content-font-size-secondary, 13px); + line-height: calc(20px + var(--dsh-content-font-delta-secondary, 0px)); white-space: pre-wrap; word-break: break-word; } diff --git a/packages/client/ui-chat/src/client/chat/StatsLine.module.css b/packages/client/ui-chat/src/client/chat/StatsLine.module.css index b2d7989cde..29c0bc3aab 100644 --- a/packages/client/ui-chat/src/client/chat/StatsLine.module.css +++ b/packages/client/ui-chat/src/client/chat/StatsLine.module.css @@ -1,5 +1,6 @@ -/* Session stats row: 12/20 tertiary text under the flow, aligned to the - shared message column axis (--dsh-chat-content-width). */ +/* Session stats row: 13/20 tertiary text (the secondary content tier) under + the flow, aligned to the shared message column axis + (--dsh-chat-content-width). */ .root { /* Block, not flex: text-overflow only elides a block's inline content, so @@ -11,8 +12,8 @@ margin: 0 auto; box-sizing: border-box; padding: 4px calc(var(--dsh-composer-side-clearance) + 16px) 0px; - font-size: calc(12px + var(--dsh-content-font-delta, 0px)); - line-height: calc(20px + var(--dsh-content-font-delta, 0px)); + font-size: var(--dsh-content-font-size-secondary, 13px); + line-height: calc(20px + var(--dsh-content-font-delta-secondary, 0px)); color: var(--dsw-alias-label-tertiary); white-space: nowrap; overflow: hidden; diff --git a/packages/client/ui-chat/src/client/chat/TurnUsageDisclosure.module.css b/packages/client/ui-chat/src/client/chat/TurnUsageDisclosure.module.css index b0a8dbad02..ba96155504 100644 --- a/packages/client/ui-chat/src/client/chat/TurnUsageDisclosure.module.css +++ b/packages/client/ui-chat/src/client/chat/TurnUsageDisclosure.module.css @@ -29,9 +29,9 @@ min-width: 0; overflow: hidden; color: var(--dsw-alias-label-tertiary); - font-size: 14px; + font-size: var(--dsh-content-font-size-secondary, 13px); font-variant-numeric: tabular-nums; - line-height: 24px; + line-height: calc(24px + var(--dsh-content-font-delta, 0px)); text-overflow: ellipsis; white-space: nowrap; } diff --git a/packages/client/ui-chat/tests/chat-font-axis-styles.client.spec.ts b/packages/client/ui-chat/tests/chat-font-axis-styles.client.spec.ts index 6f94a95ab3..d0b8c9cb3a 100644 --- a/packages/client/ui-chat/tests/chat-font-axis-styles.client.spec.ts +++ b/packages/client/ui-chat/tests/chat-font-axis-styles.client.spec.ts @@ -19,25 +19,25 @@ function declarationsFrom(source: string, selector: string): string[] { } describe('chat flow font-size axis', () => { - it('think text keeps its 2px step under the body size and moves with the delta', () => { + it('think text reads the secondary tier (one step under the body size)', () => { const css = read('ReasoningRow.module.css') for (const selector of ['.summary', '.thinkBody']) { expect(declarationsFrom(css, selector)).toEqual(expect.arrayContaining([ - 'font-size: calc(12px + var(--dsh-content-font-delta, 0px))', - 'line-height: calc(20px + var(--dsh-content-font-delta, 0px))', + 'font-size: var(--dsh-content-font-size-secondary, 13px)', + 'line-height: calc(20px + var(--dsh-content-font-delta-secondary, 0px))', ])) } }) - it('command and context summaries ride the axis at the body size', () => { + it('command and context summaries read the secondary tier on the shared row line', () => { expect(declarationsFrom(read('GenericCommandCard.module.css'), '.summary')).toEqual(expect.arrayContaining([ - 'font-size: var(--dsh-content-font-size, 14px)', + 'font-size: var(--dsh-content-font-size-secondary, 13px)', 'line-height: calc(24px + var(--dsh-content-font-delta, 0px))', ])) const context = read('ContextInjectionRow.module.css') for (const selector of ['.source', '.summary']) { expect(declarationsFrom(context, selector)).toEqual(expect.arrayContaining([ - 'font-size: var(--dsh-content-font-size, 14px)', + 'font-size: var(--dsh-content-font-size-secondary, 13px)', 'line-height: calc(24px + var(--dsh-content-font-delta, 0px))', ])) } @@ -60,7 +60,7 @@ describe('chat flow font-size axis', () => { const css = read('MessageItem.module.css') for (const selector of ['.compactionTitle', '.compactionSummary', '.compactionBody']) { expect(declarationsFrom(css, selector)).toEqual(expect.arrayContaining([ - 'font-size: var(--dsh-content-font-size, 14px)', + 'font-size: var(--dsh-content-font-size-secondary, 13px)', 'line-height: calc(24px + var(--dsh-content-font-delta, 0px))', ])) } diff --git a/packages/client/ui-message-feedback/src/client/MessageFeedbackActions.module.css b/packages/client/ui-message-feedback/src/client/MessageFeedbackActions.module.css index 6948f2eb56..a8c16c9383 100644 --- a/packages/client/ui-message-feedback/src/client/MessageFeedbackActions.module.css +++ b/packages/client/ui-message-feedback/src/client/MessageFeedbackActions.module.css @@ -46,7 +46,7 @@ border-radius: 14px; background: transparent; color: var(--dsw-alias-label-tertiary); - font-size: calc(13px + var(--dsh-content-font-delta, 0px)); + font-size: var(--dsh-content-font-size-secondary, 13px); line-height: calc(28px + var(--dsh-content-font-delta, 0px)); white-space: nowrap; text-overflow: ellipsis; diff --git a/packages/client/ui-primitives/src/DisclosureRow.module.css b/packages/client/ui-primitives/src/DisclosureRow.module.css index 212c11411b..fed453f345 100644 --- a/packages/client/ui-primitives/src/DisclosureRow.module.css +++ b/packages/client/ui-primitives/src/DisclosureRow.module.css @@ -1,8 +1,10 @@ -/* Shared disclosure header: [16px leading] gap 6 [title 14/24] at the default +/* Shared disclosure header: [16px leading] gap 6 [title 13/24] at the default size. The Settings font-size preference moves the row through the - body-published axis: title size follows --dsh-content-font-size, and the row - height, leading box, and glyph edge shift by the same px delta so the icon - keeps its optical share of the line. */ + body-published axis: title size follows the secondary tier + (--dsh-content-font-size-secondary: one step under the body — setting −1 at + ≤14, setting −2 above), and the row height, leading box, and glyph edge + shift by the body px delta so the icon keeps its optical share of the + line. */ .root { display: flex; @@ -76,7 +78,7 @@ button.leading { .title { flex: none; - font-size: var(--dsh-content-font-size, 14px); + font-size: var(--dsh-content-font-size-secondary, 13px); line-height: calc(24px + var(--dsh-content-font-delta, 0px)); color: var(--dsw-alias-label-secondary); } diff --git a/packages/client/ui-primitives/tests/disclosure-row-styles.client.spec.ts b/packages/client/ui-primitives/tests/disclosure-row-styles.client.spec.ts index 4b1ce4a4ef..52bb220b7e 100644 --- a/packages/client/ui-primitives/tests/disclosure-row-styles.client.spec.ts +++ b/packages/client/ui-primitives/tests/disclosure-row-styles.client.spec.ts @@ -19,9 +19,9 @@ function declarations(selector: string): string[] { } describe('DisclosureRow.module.css font-size axis', () => { - it('sizes the title from the content font axis with the shared px delta', () => { + it('sizes the title from the secondary content tier on the shared row line', () => { expect(declarations('.title')).toEqual(expect.arrayContaining([ - 'font-size: var(--dsh-content-font-size, 14px)', + 'font-size: var(--dsh-content-font-size-secondary, 13px)', 'line-height: calc(24px + var(--dsh-content-font-delta, 0px))', ])) }) diff --git a/packages/client/ui-theme/README.i18n.yaml b/packages/client/ui-theme/README.i18n.yaml index 63a4525d4b..376749a4f8 100644 --- a/packages/client/ui-theme/README.i18n.yaml +++ b/packages/client/ui-theme/README.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write packages/client/ui-theme/README.md -README.md: 12ea48aa2f321deec82ecea14c42aad7362523d6 -README.zh.md: a720916f5c9eab005a056415455e5017c0d08f0d +README.md: 32ec60edb39b30afdb9b54804e62302cdc58e531 +README.zh.md: ab17910ab9cec4e1ff519af0922ee27034a6fa7c diff --git a/packages/client/ui-theme/README.md b/packages/client/ui-theme/README.md index 12ea48aa2f..32ec60edb3 100644 --- a/packages/client/ui-theme/README.md +++ b/packages/client/ui-theme/README.md @@ -29,7 +29,7 @@ Users switch the color scheme and content font size from two rows in Settings (G ### Appearance and font size -The plugin registers Appearance preference cubes and a font-size stepper in the General section. The stepper accepts integer values from 12 through 17 px and defaults to 14 px. It changes conversation headings and base text by the same increment, including the user bubble and composer draft; tables, small text, and code keep fixed sizes. Each accepted change writes through the Host settings API. Rapid changes serialize in gesture order with namespace revisions, and a rejected latest write reloads the durable values. Non-loopback pages keep both choices process-local. +The plugin registers Appearance preference cubes and a font-size stepper in the General section. The stepper accepts integer values from 12 through 17 px and defaults to 14 px. It changes conversation headings and base text by the same increment, including the user bubble and composer draft; flow-row titles, summaries, and tables follow one step under the body size, while small text and code keep fixed sizes. Each accepted change writes through the Host settings API. Rapid changes serialize in gesture order with namespace revisions, and a rejected latest write reloads the durable values. Non-loopback pages keep both choices process-local. ### Registering a theme @@ -53,7 +53,7 @@ The service owns theme and font-size state and publishes snapshots. The ui-layou `src/styles/` holds five sheets imported in order by ui-theme's dynamic client entry: `base.css`, `design-platform.css`, `scrollbar.css`, `gradient-shadow-text.css`, and `shiki.css`. The client bundle compiles and injects them as plugin-owned global styles, so unload and HMR remove them with ui-theme. `scrollbar.css` is the sole consumer of the `--dsw-alias-scrollbar-*` tokens and must follow `design-platform.css`, which declares them. -`gradient-shadow-text.css` derives `--dsh-content-font-delta` from `--dsh-content-font-size` and shifts the Markdown heading and base-text ladder by that increment. Dense table, small, and code variants stay fixed. The user bubble and composer draft consume the same variables outside that ladder. +`gradient-shadow-text.css` derives `--dsh-content-font-delta` from `--dsh-content-font-size` and shifts the Markdown heading and base-text ladder by that increment. It also derives the secondary tier `--dsh-content-font-size-secondary` (setting −1 at ≤14, setting −2 above; 13px at the default) with its own `--dsh-content-font-delta-secondary` for the table variants and the flow rows one step under the body. Dense small and code variants stay fixed. Outside the ladder, the user bubble and composer draft read the body pair directly, and flow-row titles and summaries read the secondary pair. ### Scrollbar rebinding diff --git a/packages/client/ui-theme/README.zh.md b/packages/client/ui-theme/README.zh.md index a720916f5c..ab17910ab9 100644 --- a/packages/client/ui-theme/README.zh.md +++ b/packages/client/ui-theme/README.zh.md @@ -29,7 +29,7 @@ kind: "package-reference" ### 外观与字号 -插件在「通用」分区注册外观偏好方块与字号步进器。步进器接受 12 至 17 px 的整数,默认值为 14 px。它以相同增量调整会话标题与基础文本,包括用户气泡与 composer 草稿;表格、小号文本和代码保持固定字号。每次通过的变更都经 Host settings API 写入。连续快速变更按操作顺序携带命名空间 revision 串行写入,最新写入被拒时重新加载持久值。非 loopback 页面把两个选择都保留在进程内。 +插件在「通用」分区注册外观偏好方块与字号步进器。步进器接受 12 至 17 px 的整数,默认值为 14 px。它以相同增量调整会话标题与基础文本,包括用户气泡与 composer 草稿;流内行的标题、摘要与表格跟随比正文低一档的字号,小号文本和代码保持固定字号。每次通过的变更都经 Host settings API 写入。连续快速变更按操作顺序携带命名空间 revision 串行写入,最新写入被拒时重新加载持久值。非 loopback 页面把两个选择都保留在进程内。 ### 注册主题 @@ -53,7 +53,7 @@ kind: "package-reference" `src/styles/` 下有五张样式表,由 ui-theme 的动态客户端 entry 依次导入:`base.css`、`design-platform.css`、`scrollbar.css`、`gradient-shadow-text.css` 与 `shiki.css`。客户端 bundle 将其编译并注入为插件持有的全局样式,因此卸载与 HMR 会随 ui-theme 一同移除。`scrollbar.css` 是 `--dsw-alias-scrollbar-*` token 的唯一消费方,必须排在声明这些 token 的 `design-platform.css` 之后。 -`gradient-shadow-text.css` 从 `--dsh-content-font-size` 派生 `--dsh-content-font-delta`,并以该增量移动 Markdown 标题与基础文本阶梯。紧凑的表格、小号文本与代码变体保持固定字号。用户气泡与 composer 草稿在该阶梯之外消费相同变量。 +`gradient-shadow-text.css` 从 `--dsh-content-font-size` 派生 `--dsh-content-font-delta`,并以该增量移动 Markdown 标题与基础文本阶梯。它同时派生低一档变量 `--dsh-content-font-size-secondary`(设置 ≤14 时为设置值 −1,>14 时为设置值 −2;默认设置下为 13px)及配套的 `--dsh-content-font-delta-secondary`,供表格变体与比正文低一档的流内行使用。紧凑的小号文本与代码变体保持固定字号。阶梯之外,用户气泡与 composer 草稿直接读取正文档变量对,流内行的标题及摘要读取低一档变量对。 ### 滚动条重新绑定 diff --git a/packages/client/ui-theme/src/styles/gradient-shadow-text.css b/packages/client/ui-theme/src/styles/gradient-shadow-text.css index c286c6d2e2..a2d2597d89 100644 --- a/packages/client/ui-theme/src/styles/gradient-shadow-text.css +++ b/packages/client/ui-theme/src/styles/gradient-shadow-text.css @@ -22,10 +22,16 @@ body[data-ds-dark-theme] { 重新从 Figma 导出时需要保留这一缩放。 */ /* 正文字号调节:--dsh-content-font-size 由主题 bootstrap 与 ThemePresenter 写在 body 上(整数 px,12–17,默认 14)。标题与正文变体按同一像素增量 - (--dsh-content-font-delta)随动,保持层级;表格、small、code 属于密集 - 次级文本,保持固定。 */ + (--dsh-content-font-delta)随动,保持层级。低一档文本(think、工具/bash + 行的标题与摘要、markdown 表格、流内次级说明等)统一读 + --dsh-content-font-size-secondary:设置 ≤14 时为设置值 −1,>14 时为 + 设置值 −2(12→11、13→12、14→13、15→13、16→14、17→15)。式中 + max(13px,·) 的作用是让低设置取 −1 而非 −2,不是结果下限——12 设置下 + 层级触底 11px。small、code 属于密集次级文本,保持固定。 */ body { --dsh-content-font-delta: calc(var(--dsh-content-font-size, 14px) - 14px); + --dsh-content-font-size-secondary: min(calc(var(--dsh-content-font-size, 14px) - 1px), max(13px, calc(var(--dsh-content-font-size, 14px) - 2px))); + --dsh-content-font-delta-secondary: calc(var(--dsh-content-font-size-secondary) - 13px); --dsw-font-markdown-h1: 700 calc(21px + var(--dsh-content-font-delta)) / calc(30px + var(--dsh-content-font-delta)) var(--dsw-font-family); --dsw-font-markdown-h1-font-family: var(--dsw-font-family); @@ -83,18 +89,18 @@ body { --dsw-font-markdown-base-strong-italic-font-size: var(--dsh-content-font-size, 14px); --dsw-font-markdown-base-strong-italic-font-style: italic; - --dsw-font-markdown-table: 13px/22px var(--dsw-font-family); + --dsw-font-markdown-table: var(--dsh-content-font-size-secondary, 13px)/calc(22px + var(--dsh-content-font-delta-secondary, 0px)) var(--dsw-font-family); --dsw-font-markdown-table-font-family: var(--dsw-font-family); --dsw-font-markdown-table-font-weight: 400; - --dsw-font-markdown-table-line-height: 22px; - --dsw-font-markdown-table-font-size: 13px; + --dsw-font-markdown-table-line-height: calc(22px + var(--dsh-content-font-delta-secondary, 0px)); + --dsw-font-markdown-table-font-size: var(--dsh-content-font-size-secondary, 13px); --dsw-font-markdown-table-font-style: normal; - --dsw-font-markdown-table-head: 500 13px/22px var(--dsw-font-family); + --dsw-font-markdown-table-head: 500 var(--dsh-content-font-size-secondary, 13px)/calc(22px + var(--dsh-content-font-delta-secondary, 0px)) var(--dsw-font-family); --dsw-font-markdown-table-head-font-family: var(--dsw-font-family); --dsw-font-markdown-table-head-font-weight: 500; - --dsw-font-markdown-table-head-line-height: 22px; - --dsw-font-markdown-table-head-font-size: 13px; + --dsw-font-markdown-table-head-line-height: calc(22px + var(--dsh-content-font-delta-secondary, 0px)); + --dsw-font-markdown-table-head-font-size: var(--dsh-content-font-size-secondary, 13px); --dsw-font-markdown-table-head-font-style: normal; --dsw-font-markdown-small: 12px/20px var(--dsw-font-family); diff --git a/packages/client/ui-tool/src/client/tool/components/ToolRow.module.css b/packages/client/ui-tool/src/client/tool/components/ToolRow.module.css index 7deef20ea8..4a3d5e46ef 100644 --- a/packages/client/ui-tool/src/client/tool/components/ToolRow.module.css +++ b/packages/client/ui-tool/src/client/tool/components/ToolRow.module.css @@ -1,8 +1,10 @@ /* Tool summary row (figma 122:9479): 24px single line at the default size — - [16 leading] gap6 [title 14/24] gap8 [2x2 dot] gap8 [summary FILL truncate]. + [16 leading] gap6 [title 13/24] gap8 [2x2 dot] gap8 [summary FILL truncate]. The Settings font-size preference rides the body-published axis: the shared - DisclosureRow chrome scales the row height, title, and leading glyph; the - summary texts here follow the same size and px delta. */ + DisclosureRow chrome scales the row height and leading glyph by the body px + delta; the title and the summary texts here read the secondary tier + (--dsh-content-font-size-secondary: one step under the body — setting −1 at + ≤14, setting −2 above), matching think text. */ .root { display: flex; @@ -82,7 +84,7 @@ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - font-size: var(--dsh-content-font-size, 14px); + font-size: var(--dsh-content-font-size-secondary, 13px); line-height: calc(24px + var(--dsh-content-font-delta, 0px)); color: var(--dsw-alias-label-tertiary); } @@ -96,7 +98,7 @@ flex: none; margin-left: 4px; white-space: nowrap; - font-size: var(--dsh-content-font-size, 14px); + font-size: var(--dsh-content-font-size-secondary, 13px); line-height: calc(24px + var(--dsh-content-font-delta, 0px)); color: var(--dsw-alias-label-tertiary); } @@ -114,7 +116,7 @@ background: none; font: inherit; text-align: left; - font-size: var(--dsh-content-font-size, 14px); + font-size: var(--dsh-content-font-size-secondary, 13px); line-height: calc(24px + var(--dsh-content-font-delta, 0px)); color: var(--dsw-alias-label-secondary); text-decoration: underline; diff --git a/packages/client/ui-tool/src/client/tool/toolviews/bash-sample.module.css b/packages/client/ui-tool/src/client/tool/toolviews/bash-sample.module.css index fbbab8cbbc..4c1d7b18b0 100644 --- a/packages/client/ui-tool/src/client/tool/toolviews/bash-sample.module.css +++ b/packages/client/ui-tool/src/client/tool/toolviews/bash-sample.module.css @@ -170,7 +170,7 @@ .title { flex: none; - font-size: var(--dsh-content-font-size, 14px); + font-size: var(--dsh-content-font-size-secondary, 13px); line-height: calc(24px + var(--dsh-content-font-delta, 0px)); color: var(--dsw-alias-label-secondary); } @@ -190,7 +190,7 @@ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - font-size: var(--dsh-content-font-size, 14px); + font-size: var(--dsh-content-font-size-secondary, 13px); line-height: calc(24px + var(--dsh-content-font-delta, 0px)); color: var(--dsw-alias-label-tertiary); } diff --git a/packages/client/ui-tool/tests/tool-row-styles.client.spec.ts b/packages/client/ui-tool/tests/tool-row-styles.client.spec.ts index 1a48bbdad8..28913a2939 100644 --- a/packages/client/ui-tool/tests/tool-row-styles.client.spec.ts +++ b/packages/client/ui-tool/tests/tool-row-styles.client.spec.ts @@ -43,12 +43,13 @@ describe('ToolRow.module.css summary line', () => { expect(declarations('.summarySuffix')).not.toEqual(expect.arrayContaining(['text-overflow: ellipsis'])) }) - it('sizes the summary texts from the content font axis', () => { + it('sizes the summary texts from the secondary content tier', () => { // The Settings font-size preference must reach tool-call rows, not only - // the narration body: summary, suffix, and file link ride the axis. + // the narration body: summary, suffix, and file link read the secondary + // tier (one step under the body), matching think text. for (const selector of ['.summary', '.summarySuffix', '.fileLink']) { expect(declarations(selector)).toEqual(expect.arrayContaining([ - 'font-size: var(--dsh-content-font-size, 14px)', + 'font-size: var(--dsh-content-font-size-secondary, 13px)', 'line-height: calc(24px + var(--dsh-content-font-delta, 0px))', ])) } diff --git a/packages/client/ui-workflow-run/src/client/WorkflowRunPanel.module.css b/packages/client/ui-workflow-run/src/client/WorkflowRunPanel.module.css index b7678eea03..aa4ff56a3d 100644 --- a/packages/client/ui-workflow-run/src/client/WorkflowRunPanel.module.css +++ b/packages/client/ui-workflow-run/src/client/WorkflowRunPanel.module.css @@ -37,7 +37,7 @@ flex: none; max-width: 42%; color: var(--dsw-alias-label-secondary); - font-size: var(--dsh-content-font-size, 14px); + font-size: var(--dsh-content-font-size-secondary, 13px); font-weight: 510; line-height: calc(24px + var(--dsh-content-font-delta, 0px)); text-overflow: ellipsis; @@ -49,8 +49,8 @@ flex: 1; min-width: 0; color: var(--dsw-alias-label-tertiary); - font-size: calc(12px + var(--dsh-content-font-delta, 0px)); - line-height: calc(18px + var(--dsh-content-font-delta, 0px)); + font-size: var(--dsh-content-font-size-secondary, 13px); + line-height: calc(18px + var(--dsh-content-font-delta-secondary, 0px)); text-overflow: ellipsis; white-space: nowrap; } @@ -102,7 +102,7 @@ min-width: 0; max-width: 42%; color: var(--dsw-alias-label-secondary); - font-size: var(--dsh-content-font-size, 14px); + font-size: var(--dsh-content-font-size-secondary, 13px); line-height: calc(24px + var(--dsh-content-font-delta, 0px)); text-overflow: ellipsis; white-space: nowrap; @@ -113,8 +113,8 @@ flex: 1; min-width: 0; color: var(--dsw-alias-label-tertiary); - font-size: calc(13px + var(--dsh-content-font-delta, 0px)); - line-height: calc(20px + var(--dsh-content-font-delta, 0px)); + font-size: var(--dsh-content-font-size-secondary, 13px); + line-height: calc(20px + var(--dsh-content-font-delta-secondary, 0px)); text-overflow: ellipsis; white-space: nowrap; } @@ -124,10 +124,10 @@ flex: none; /* Column width scales with the text (~132/13 ≈ 10px per font-size px) so larger sizes keep the same status text visible instead of truncating. */ - width: calc(132px + var(--dsh-content-font-delta, 0px) * 10); + width: calc(132px + var(--dsh-content-font-delta-secondary, 0px) * 10); color: var(--dsw-alias-label-secondary); - font-size: calc(13px + var(--dsh-content-font-delta, 0px)); - line-height: calc(20px + var(--dsh-content-font-delta, 0px)); + font-size: var(--dsh-content-font-size-secondary, 13px); + line-height: calc(20px + var(--dsh-content-font-delta-secondary, 0px)); text-align: right; text-overflow: ellipsis; white-space: nowrap; @@ -223,6 +223,9 @@ flex: 1; min-width: 0; color: var(--dsw-alias-label-secondary); + /* Body size, not the secondary tier: the member label is the panel's + content (an agent's task), while the run/phase headers, counts, and + statuses around it are chrome one step down. */ font-size: var(--dsh-content-font-size, 14px); line-height: calc(24px + var(--dsh-content-font-delta, 0px)); text-overflow: ellipsis; @@ -234,8 +237,8 @@ overflow: hidden; width: 64px; color: var(--dsw-alias-label-secondary); - font-size: calc(13px + var(--dsh-content-font-delta, 0px)); - line-height: calc(20px + var(--dsh-content-font-delta, 0px)); + font-size: var(--dsh-content-font-size-secondary, 13px); + line-height: calc(20px + var(--dsh-content-font-delta-secondary, 0px)); text-align: right; text-overflow: ellipsis; white-space: nowrap; @@ -243,8 +246,8 @@ .empty { color: var(--dsw-alias-label-tertiary); - font-size: calc(13px + var(--dsh-content-font-delta, 0px)); - line-height: calc(20px + var(--dsh-content-font-delta, 0px)); + font-size: var(--dsh-content-font-size-secondary, 13px); + line-height: calc(20px + var(--dsh-content-font-delta-secondary, 0px)); padding: 0; } diff --git a/packages/client/ui-workflow-run/tests/panel-styles.client.spec.ts b/packages/client/ui-workflow-run/tests/panel-styles.client.spec.ts index 4530bee2f5..0095a47bbf 100644 --- a/packages/client/ui-workflow-run/tests/panel-styles.client.spec.ts +++ b/packages/client/ui-workflow-run/tests/panel-styles.client.spec.ts @@ -1,8 +1,10 @@ /** * WorkflowRunPanel's font-size-axis adoption as CSS text. jsdom has no * layout, so these read the declarations that make the run/phase headers and - * the expanded member rows follow the Settings font-size preference through - * --dsh-content-font-size / --dsh-content-font-delta. + * the expanded member rows follow the Settings font-size preference: member + * labels at the body size (--dsh-content-font-size / --dsh-content-font-delta), + * the chrome around them on the secondary tier + * (--dsh-content-font-size-secondary / --dsh-content-font-delta-secondary). */ import { readFileSync } from 'node:fs' import { fileURLToPath } from 'node:url' @@ -31,18 +33,18 @@ describe('WorkflowRunPanel.module.css font-size axis', () => { ])) }) - it('member status and the empty placeholder keep their 1px step under the body', () => { + it('member status and the empty placeholder read the secondary tier', () => { for (const selector of ['.memberStatus', '.empty']) { expect(declarations(selector)).toEqual(expect.arrayContaining([ - 'font-size: calc(13px + var(--dsh-content-font-delta, 0px))', - 'line-height: calc(20px + var(--dsh-content-font-delta, 0px))', + 'font-size: var(--dsh-content-font-size-secondary, 13px)', + 'line-height: calc(20px + var(--dsh-content-font-delta-secondary, 0px))', ])) } }) it('the phase status column widens with the text so larger sizes do not truncate', () => { expect(declarations('.phaseStatus')).toEqual(expect.arrayContaining([ - 'width: calc(132px + var(--dsh-content-font-delta, 0px) * 10)', + 'width: calc(132px + var(--dsh-content-font-delta-secondary, 0px) * 10)', ])) }) })