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() { >