From ad59ccc2e2fde41cbe66831d913528b65fcf4235 Mon Sep 17 00:00:00 2001
From: Luke Parker <10430890+Hona@users.noreply.github.com>
Date: Sun, 23 Aug 2026 13:47:17 +1000
Subject: [PATCH] fix(ui): standardize safe text metrics (#44106)
---
packages/app/AGENTS.md | 6 ++++
.../session-timeline-notices.spec.ts | 8 +++--
.../session-timeline-tool-projection.spec.ts | 5 ++--
packages/app/src/home/sessions/view.tsx | 2 +-
packages/app/src/new-session/view.tsx | 2 +-
packages/app/src/providers/connect/dialog.tsx | 4 +--
packages/app/src/servers/wsl/dialog.css | 2 +-
.../src/session/timeline/message-timeline.tsx | 2 +-
packages/app/src/settings/settings.css | 30 +++++++++----------
.../settings/workspaces/project-dialog.css | 2 +-
.../settings/workspaces/project-dialog.tsx | 4 +--
packages/app/src/shell/debug/debug-bar.tsx | 6 ++--
.../app/src/shell/titlebar/tab-popover.css | 2 +-
packages/session-ui/AGENTS.md | 7 +++++
.../session-ui/src/components/basic-tool.css | 5 ++--
.../src/components/message-part.css | 5 ++--
.../src/timeline/session-timeline-row.tsx | 6 ++--
.../session-ui/src/tools/tool-renderer.tsx | 7 ++---
.../src/v2/components/session-review-v2.css | 10 +++----
packages/ui/AGENTS.md | 7 +++++
.../line-comment/line-comment.css | 6 ++--
packages/ui/src/forms/field/field.css | 2 +-
.../ui/src/forms/text-input/text-input.css | 2 +-
packages/ui/src/navigation/menu/menu.css | 2 +-
.../segmented-control/segmented-control.css | 2 +-
.../ui/src/navigation/tabs/tabs-current.css | 2 +-
packages/ui/src/styles/tailwind/index.css | 3 ++
packages/ui/src/styles/tokens/theme.css | 3 ++
28 files changed, 86 insertions(+), 58 deletions(-)
diff --git a/packages/app/AGENTS.md b/packages/app/AGENTS.md
index 2af9fb558b8..41cdb347daf 100644
--- a/packages/app/AGENTS.md
+++ b/packages/app/AGENTS.md
@@ -19,6 +19,12 @@
- Always prefer `createStore` over multiple `createSignal` calls
+## Typography
+
+- Use `--line-height-compact` (`16px`) for `13px` compact UI text and `--line-height-base` (`20px`) for body text.
+- Do not use `leading-none`, `line-height: 1`, or a `13px` line height for normal text. Inter descenders clip inside truncation and overflow containers.
+- Keep control and row heights explicit. Fix font metrics directly rather than using transforms, negative margins, or clip-padding compensation.
+
## Localization
- NEVER hardcode user-visible English strings in production code. ALWAYS use an i18n key for visible copy, placeholders, accessible labels, tooltips, menus, dialogs, toasts, empty states, and displayed errors.
diff --git a/packages/app/e2e/regression/session-timeline-notices.spec.ts b/packages/app/e2e/regression/session-timeline-notices.spec.ts
index ae1e9ffdc3d..bc420ff26c0 100644
--- a/packages/app/e2e/regression/session-timeline-notices.spec.ts
+++ b/packages/app/e2e/regression/session-timeline-notices.spec.ts
@@ -86,10 +86,12 @@ test("shows a delegating row while subagent input streams", async ({ page }) =>
const delegating = page.locator('[data-component="task-tool-delegating"]')
await expect(delegating).toBeVisible()
- await expect(delegating.locator('[data-component="text-shimmer"]')).toHaveAttribute(
+ const shimmer = delegating.locator('[data-component="text-shimmer"]')
+ await expect(shimmer).toHaveAttribute(
"aria-label",
"Delegating agent...",
)
+ await expect(shimmer).toHaveCSS("line-height", "16px")
const icon = delegating.locator('[data-slot="icon-svg"]')
await expect(icon.locator('use[href="#opencode-v2-icon-subagent"]')).toBeVisible()
await expect(icon).toHaveCSS("color", "rgb(174, 174, 174)")
@@ -127,11 +129,11 @@ test("renders the moved location notice in its compact timeline style", async ({
await expect(notice).toHaveCSS("padding-bottom", "4px")
await expect(label).toHaveCSS("font-size", "13px")
await expect(label).toHaveCSS("font-weight", "530")
- await expect(label).toHaveCSS("line-height", "13px")
+ await expect(label).toHaveCSS("line-height", "16px")
await expect(label).toHaveCSS("color", "rgb(128, 128, 128)")
await expect(value).toHaveCSS("font-size", "13px")
await expect(value).toHaveCSS("font-weight", "440")
- await expect(value).toHaveCSS("line-height", "13px")
+ await expect(value).toHaveCSS("line-height", "16px")
await expect(value).toHaveCSS("color", "rgb(128, 128, 128)")
await expect(value).toHaveCSS("text-overflow", "ellipsis")
await expect(value).toHaveCSS("white-space", "nowrap")
diff --git a/packages/app/e2e/regression/session-timeline-tool-projection.spec.ts b/packages/app/e2e/regression/session-timeline-tool-projection.spec.ts
index ec745c44b82..ab8af77c726 100644
--- a/packages/app/e2e/regression/session-timeline-tool-projection.spec.ts
+++ b/packages/app/e2e/regression/session-timeline-tool-projection.spec.ts
@@ -121,19 +121,20 @@ test("labels skill tools from IDs and result metadata", async ({ page }) => {
messages: [
userMessage(),
assistantMessage([
- toolPart(pending, "skill", "running", { id: "sample-skill" }),
+ toolPart(pending, "skill", "running", { id: "frontend-design" }),
toolPart(completed, "skill", "completed", { id: "opencode" }, { metadata: { name: "OpenCode" } }),
]),
],
})
for (const [id, name] of [
- [pending, "sample-skill"],
+ [pending, "frontend-design"],
[completed, "OpenCode"],
] as const) {
const skill = page.locator(`[data-timeline-part-id="${id}"]`)
const loaded = skill.locator('[data-component="tool-loaded-item"]')
await expect(loaded).toHaveAttribute("aria-label", `Loaded ${name} skill`)
+ await expect(loaded).toHaveCSS("line-height", "16px")
await expect(loaded.locator('[data-slot="tool-loaded-label"]')).toHaveText("Loaded")
await expect(loaded.locator('[data-slot="tool-loaded-kind"]')).toHaveText("skill")
await expect(loaded.locator('[data-component="text-shimmer"]')).toHaveAttribute("aria-label", name)
diff --git a/packages/app/src/home/sessions/view.tsx b/packages/app/src/home/sessions/view.tsx
index a4515e31e87..60a4c8f4320 100644
--- a/packages/app/src/home/sessions/view.tsx
+++ b/packages/app/src/home/sessions/view.tsx
@@ -509,7 +509,7 @@ function HomeSessionsEmpty(props: { onNewSession?: () => void; language: ReturnT
diff --git a/packages/app/src/new-session/view.tsx b/packages/app/src/new-session/view.tsx
index a639f9d26b2..fe1e3b374d9 100644
--- a/packages/app/src/new-session/view.tsx
+++ b/packages/app/src/new-session/view.tsx
@@ -139,7 +139,7 @@ function ProviderTip() {
>