Transcript: a reply's buttons come first at the prose edge, its time on hover; the last reply's show at rest
Leo, 2026-11-02 00:28Z: "this should not be placed in front of the copy/whatever buttons. those buttons should always just be there left aligned"
Leo, 2026-11-02 00:29Z: "i should be able to see the copy buttons on your responses when your things end"
Leo, 2026-11-02 00:35Z: "compared to claude code our bottom thing looks bad is sized bad all around spaced bad + the useless text at the front + didn't i always say we can do it like chatgpt / i assume the x previous messages are when there's a mix and the worked for is if it's one contiguous thing. notice how on hover it reveals the exact timestamp. let's follow those."
What changes
The reply footer (TurnRows.tsx TurnFooter, MessageActions.tsx ReplyActions) now follows ChatGPT's row:
- The buttons come first, at the prose's left edge. "Worked for 13s Ā· ā 359 out ā 328.8K in" is gone from the row. It is now the time's tooltip, so the numbers can still be read. The first glyph's ink sits exactly on col-left (design/grid.md 5.5). It used to sit 6px left, because the row's
inset-inlineoverhang and the first button's margin both pulled it left. The row now starts on the column and overhangs only at its end. - The time comes after the buttons, hidden at rest, shown on hover. It is ChatGPT's exact time ("Oct 18, 5:41 AM", with the year only when it isn't this year) instead of "3 minutes ago". It keeps its space, so nothing moves.
- The finished chat's last reply shows its buttons at rest. #31503 landed that on base while this PR was open, and this PR now relies on its
acpmux-row--final-footerand tests it. Earlier footers still show on hover.
Regressing PR: #30176 (e9f24968, "a finished Claude turn folds per run"). It set folded = false for Claude turns, so turns.ts footerSays() became true for every Claude turn, and TurnFooter drew the "Worked for Ā· tokens" label ahead of the buttons on every Claude reply. The label was added in #16612 and its tokens in #24259; before #30176 it only showed for turns that had no fold. #31505 (merged while this PR was open) moved the label after the buttons. This PR takes it out of the row and puts it in the time's tooltip, as the ChatGPT reference does, and updates #31505's test to match.
Not in this PR. These follow separately:
- ChatGPT's sizing and vertical rhythm (a 20px glyph in a 32px button, 8 above and 24 below). It changes the row-height model and lands together with the transcript-spacing lane's table.
- The "Worked for >" / "N previous messages >" header with a hairline rule, for Codex turns. Claude turns keep #30176's per-run folding, per Leo's 11-01 "claude gets claude behaviour, codex gets codex".
Tool-row spacing and the composer are untouched.
Tests (red at base, green at head)
webviews/test/reply-footer.test.ts(new, Chromium, light and dark):- In every footer the first child is the button group, and the first glyph's ink is 0px from the prose edge, both for a footer with time and tokens and for one without. The time sits after the last button.
- In a finished chat, the last reply's buttons have opacity 1 with no pointer and its time has opacity 0. On hover the time is 1 and the buttons don't move. Earlier footers stay hidden.
- At base: 4 of 4 fail (ink at -6px, the label first, the last footer hidden).
webviews/test/transcript-row-alignment.test.ts: the "footer label" lead is removed, since footers have no label now. With #31475's test changes merged in, it passes at this head. At base it fails withfooter actions "first glyph" starts at -6pxandfooter label "Worked for 5s" starts at 52px.TurnFooter.test.tsx: the label is in the time'stitleand not in the row. A footer whose only content was its label is now empty.- Typecheck,
check:design-tokens,vp fmt --checkandvp lintpass (cmux-ci 32-vCPU Linux).
Gallery: agent-pane.transcript-row-alignment gets finished (rest) and finished-hover variants, and its footer variant points at the buttons. The design spec is updated in a separate leo-workspace PR (design/chat-transcript.md).
Viewed after image: yes. 2x captures of the last reply at rest and on hover, light and dark (synthetic gallery data): the copy glyph's ink lines up with the reply's first letter, nothing shows before the buttons, and "Oct 6, 9:25 AM" appears 8px after the last button only on hover.
Remaining reds are base reds: check:design-tokens (a pages/changelog baseline that can shrink), and the row-gap and footer-height assertions that #31475 updates.
Risk: low. CSS and markup in the reply footer only. A footer whose only content was "Worked for Ns" (no text to copy) now takes no line of its own, the same as one under a second.
Agent session: agent session
š¤ Generated with Claude Code