fix(chat): trim follow-up chip labels at the character level - #7125
Conversation
line-clamp-1 ellipsizes after the last whole word that fits, so a label whose line break lands before a wide word renders with up to a word's width of dead space between the ellipsis and the chip edge. text-overflow trims per character, so the ellipsis sits flush at every width. The span is explicitly block because the chip button is not a flex container and overflow cannot clip an inline span. Also teach the injected [OPTIONS:] instruction to keep option labels short (at most ~8 words): the chip row renders each label on one line, so generation-side length control reduces how often truncation happens at all, while the CSS trim remains the guarantee.
GPT 5.6 Review (fork) — ✅ no blocking findingsReviewed Review detailsNo findings. |
UX Review (Fable 5, fork) — ✅ PASSUX-level review of
UX-Verdict: PASS Character-flush ellipsis matches the product's standard [UX-REVIEWED] 7c3ca70 |
Opus 4.8 Review (fork) — ✅ no blocking findingsReviewed |
Design Review (Fable 5, fork) — ✅ PASSDesign-level review of Tests pin substrings/markers, not the full literal — the claim in the description holds. The chip width cap ( Design-Verdict: PASS Character-level trim fixes the actual clamp mechanism, prompt guidance attacks the label-length cause, and both reuse existing patterns — sound and proportionate. [DESIGN-REVIEWED] 7c3ca70 |
First Principles Review (Fable 5, fork) — ✅ PASSPremise-level review of All checks complete. The screenshots follow the documented First-Principles-Verdict: PASS A dogfooded rendering defect fixed at both levels — display trim at character granularity, plus the generation-side cause (over-long labels) addressed in the same prompt block. What this change shipsIntent: make truncated follow-up chips look deliberately truncated instead of broken, and make the model stop generating labels that need truncating — a FIX.
No new config key, flag, or exported surface: the diff adds prose to an existing constant and swaps CSS classes, so consumer-count and one-way-door lenses have nothing to bite. The 4 other [FIRST-PRINCIPLES-REVIEWED] 7c3ca70 |
Open PR relationship auditThis is a consolidated, point-in-time code-level audit note. It compares complete merge-base diffs and current/merged code; it does not treat a shared topic as duplication or partial coverage as completion. Relationship findings
No PR, Issue, label, branch, or review state was changed by the relationship-note portion of this audit. |
Problem / Motivation
A truncated follow-up chip sometimes renders its ellipsis with a wide dead gap before the chip edge:
line-clamp-1ellipsizes after the last whole word that fits, so when the line break lands before a wide word (e.g. "…and video| support looks like") the label shows…video…followed by up to a word's width of empty space. Separately, nothing tells the model that option labels render on one line, so generated labels routinely exceed what a chip can show.Why it matters
The gap looks broken — users read it as a rendering bug rather than truncation. And every over-long generated label guarantees a truncated chip, so the display-side trim gets exercised far more often than it needs to be.
What changed (motivation → approach → change)
ChipLabelswapsline-clamp-1 break-wordsforblock truncate:text-overflow: ellipsistrims at the character level, so the ellipsis sits flush against the chip edge at every width.blockis required because the chip button is not a flex container andoverflowcannot clip an inline span. Same mechanism the collapsed tool labels use.[OPTIONS:]critical rule gains one sentence: keep each option label to at most ~8 words, putting detail in the body. Generation-side length control reduces how often truncation happens; the CSS trim remains the guarantee for labels that exceed it anyway.Tests
website/src/test/FollowUpBar.test.tsx: assertions updated fromline-clamp-1/break-wordstotruncate/block— 42/42 pass.test/test_context.py,test/test_context_marker_neutralization.py,test/metrics/test_context_blocks.py,test/test_subagent_context_groups.py— 166 pass.tsc -bclean,eslintclean on changed files,black/isort/flake8clean oncontext.py.Manual verification
Drove the existing
capture/followup-chip-columns.htmlharness with the reported label across 12 viewport widths (840–1280px), before and after: every before-width shows the word-boundary gap, every after-width shows a flush character-level trim.Screenshots / video
Before —
line-clamp-1ellipsizes after the last word, leaving a dead gap:After —
truncatetrims per character, ellipsis flush:Stacked with a guide line at the old ellipsis position:
Related Issues
no linked issue: found while dogfooding the follow-up chips shipped in #6609; the gap is a rendering behavior of the clamp mechanism, not a regression from that PR.
Checklist
feat|fix|docs|refactor|perf|test|chore|ci|build|revert: ...)Contribution License Agreement
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.