Skip to content

Stop the AI chat header truncating its title when there is room for it - #3530

Merged
malibio merged 2 commits into
mainfrom
issue-3526-chat-header-title
Oct 4, 2026
Merged

malibio merged 2 commits into
mainfrom
issue-3526-chat-header-title

Conversation

@malibio

@malibio malibio commented Oct 4, 2026

Copy link
Copy Markdown
Collaborator

Closes #3526

Problem

The chat header cut every title short by about 0.5rem: a new chat read "Untit…" with the row empty beside it.

  • The title button's width: 100% included its own horizontal padding, so the text had less room than it needed.
  • The left side of the header shrank to the title instead of taking the free space.

Fix

In ai-chat-header.svelte, which both chat viewers (native and PTY) share:

  • The left side takes the free space (flex: 1), so a long title truncates only where it reaches the model selector.
  • The rename button and the input it turns into share one box: padding and a 1px border around the text, pulled back by the same negative margin, with the width allowance giving that padding and border back. The text sits on the header's left edge in both and doesn't move between display and edit mode.
  • The h2 no longer clips, so the hover background shows its full padding.

Tests

New browser-mode test src/tests/browser/ai-chat-header-title.test.ts:

  • a short title shows in full (scrollWidth ≤ clientWidth)
  • a long title truncates, its text runs the full width of the left side, and the button stops short of the actions
  • the text's left edge, top and height are unchanged when switching to edit mode

The first two fail without the fix. bun run test:changed passes (frontend unit and Chromium browser tiers).

🤖 Generated with Claude Code

@malibio

malibio commented Oct 4, 2026

Copy link
Copy Markdown
Collaborator Author

Pragmatic Code Review — PR #3530

Review Type: Initial review (no prior reviews or comments on the PR). Reviewed commit b2ca6080, the whole diff against origin/main.

Verdict: APPROVE. No critical or important findings. The CSS fixes both root causes named in the issue, and the tests discriminate the bug.

Requirements Check (issue #3526)

# Acceptance criterion Status Basis
1 A short title ("Untitled") shows in full ✅ Test shows a short title in full passes (ran it); CSS read confirms the button now sizes to its content
2 A long title truncates before the model selector, and not earlier ✅ Test truncates a long title only where it reaches the actions passes (ran it)
3 Hover target keeps its padding; text doesn't shift between display and edit mode ✅ Test keeps the text in place when switching to edit mode passes (ran it); padding asserted > 0
4 Both chat viewers (native and PTY) are fixed ✅ Read: both import the one ai-chat-header.svelte; no other file defines chat-viewer-* styles
5 Browser-mode test asserts scrollWidth ≤ clientWidth for a short title ✅ Present, in src/tests/browser/
6 Passes bun run quality:fix Not verified Not run in this review
7 Tests pass (bun run test:changed) Partly verified Only the new browser file was run (3/3 pass, Chromium); the rest is the PR's claim

Code Review Findings

🔴 Critical

None.

🟡 Important

None.

🟢 Suggestions

  • 📁 packages/desktop-app/src/tests/browser/ai-chat-header-title.test.ts (whole file): run it once under WebKit before merge (bun run --cwd packages/desktop-app test:webkit src/tests/browser/ai-chat-header-title.test.ts). The app ships in Tauri's WebKit webview, and this review only ran Chromium. The two places an engine could differ are the scrollWidth <= clientWidth comparison on a shrink-to-fit button with a fractional text width (both values are integer-rounded, and engines round differently), and the <input> height matching the button's to one decimal place. Principle: test in the engine you ship.
  • 📁 packages/desktop-app/src/tests/browser/ai-chat-header-title.test.ts:113: expect(leftRect.width).toBeGreaterThan(HEADER_WIDTH - ACTIONS_WIDTH - 64) doesn't discriminate for a long title. The old CSS also gave the left side that width, because a max-content basis shrinks to the same 236px. The assertion that carries this test is textRight ≈ leftRect.right on the line above. To pin "the left side takes the free space", assert the width in the short-title test instead, where the old layout shrank the left side to the text; there the 64 can become the exact 2rem padding plus 0.75rem gap.
  • 📁 packages/desktop-app/src/tests/browser/ai-chat-header-title.test.ts:44-52: the PTY viewer renders the header with no actions. One short-title case rendered without the snippet would cover the fourth criterion by test rather than by shared code. Optional: the CSS path is identical.

Nits

  • Nit: 📁 packages/desktop-app/src/tests/browser/ai-chat-header-title.test.ts:136-138: the PR body says the first two tests fail without the fix. By my reading the third fails too: the old input had a 1px border the button lacked, so textLeft differed by 1px. That is a second bug this PR fixes and worth a clause in the description.
  • Nit: 📁 packages/desktop-app/src/lib/components/viewers/ai-chat-header.svelte:173-181: the rename target is still only as wide as the text, as before, so the empty part of the row isn't clickable. Not in scope; mentioned only because flex: 1 now makes a full-width target a one-line change if wanted.

What I checked in the CSS (read, not run, unless stated)

  • Horizontal box model. The button and the input have box-sizing: border-box, 1px border, 0.25rem padding and a margin of -(0.25rem + 1px), so the text starts on the container's left edge in both. The button is display: block with width: auto, which for a button is shrink-to-fit, capped at 100% + 2 × inset; its content box is therefore at most the container width. The input takes exactly that width. Setting box-sizing explicitly matters: without Tailwind preflight an <input> is content-box, so the rule holds with or without the app's global styles.
  • Vertical box model. The vertical margin cancels padding plus border in both modes. The h2 and the input are flex items, so the negative margins don't collapse through them, and the header's height is the line height in both modes. The old input's border made the header 2px taller in edit mode; that is gone.
  • Flex. flex: 1 sets the basis to 0, so the nowrap title's max-content width no longer sizes the left side; min-width: 0 was already there. The percentage max-width and width resolve against a definite width, because the h2 is stretched in a column flex container.
  • Overflow. Removing overflow: hidden from the h2 is right: the button does the clipping, and the h2 was cutting off the button's padding and its focus outline. At full width the button extends 0.25rem + 1px into the 0.75rem gap, short of the actions (asserted by test, ran it).
  • Global styles. app.css loads Tailwind preflight and * { border-color: hsl(var(--border)) } in @layer base. The component's scoped, unlayered rules win, so the transparent border stays transparent and padding, font and background are the component's. The browser test doesn't load app.css; given the explicit box-sizing, border and font: inherit, I'd expect the same layout in the app, but that is inference.
  • Standards. No lint suppression, no {@html}, no logging, no new dependency, no node-type or Pro-boundary surface. The nodeType and lifecycleStatus literals are test fixture data. The comment explains why, not what. The change is atomic.
  • Security / performance. CSS only; nothing to report.

Verified by running vs. inferred

  • Ran: bun run --cwd packages/desktop-app test:browser src/tests/browser/ai-chat-header-title.test.ts — 3 passed, Chromium.
  • Inferred from reading: that the tests fail on the old CSS (I didn't revert the file), WebKit behaviour, behaviour under preflight in the real app, quality:fix, and the rest of test:changed.

Recommendation

APPROVE. A net improvement with a small, well-explained diff. The WebKit run is the one thing I'd do before merging.

@malibio malibio left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated pragmatic-code-review: APPROVE (posted as a comment — GitHub blocks self-approval). Full findings in the review comment above.

@malibio

malibio commented Oct 4, 2026

Copy link
Copy Markdown
Collaborator Author

Review addressed (08a6f16)

Addressed

  • WebKit run: ran the new test file under test:webkit — 4 passed (and 4 passed in Chromium).
  • Non-discriminating width assertion: removed the loose bound from the long-title case; the short-title case now asserts the left side's exact width (header minus padding, gap and actions), which the old layout failed.
  • Header without actions: added a short-title case rendered with no actions snippet, as the PTY viewer renders it.

Skipped

  • Full-width rename target: out of scope for this issue; the hover target stays as wide as the title.
  • PR description nit: left as written. The description records what was observed: against the old CSS, with the edit-mode assertion as first written, the first two cases failed and the third passed. The edit-mode assertions were tightened afterwards and not re-run against the old CSS.

Re-Review Decision

Decision: NO RE-REVIEW NEEDED

Rationale: test-only changes that follow the reviewer's suggestions directly; no product code changed since the reviewed commit.

malibio and others added 2 commits October 4, 2026 16:33
closes #3526)

The title button's 100% width included its own padding, so the text always
had 0.5rem less room than it needed, and the left side of the header shrank
to the title instead of taking the free space. The left side now fills the
row, and the rename button and the input it turns into share one box whose
padding and border sit outside the text's width.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… without actions

- Assert the left side's exact width in the short-title case, where the old
  layout shrank it to the text; the long-title bound it replaces held under
  the old layout too.
- Add a short-title case with no actions, as the PTY viewer renders it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@malibio
malibio force-pushed the issue-3526-chat-header-title branch from 08a6f16 to 46324e3 Compare October 4, 2026 14:33
@malibio
malibio merged commit 66927ba into main Oct 4, 2026
@malibio
malibio deleted the issue-3526-chat-header-title branch October 4, 2026 14:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stop the AI chat header truncating its title when there is room for it

1 participant