feat(chat): your turn sits right, the assistant's stays left — T6 - #74
Merged
Conversation
docs/CHAT-TYPOGRAPHY.md D8, taken from the reference: in the Claude Code console your
messages are right-aligned bubbles and the replies are left-aligned prose.
This is the half T4 was missing, and it closes a risk T4 opened rather than adding polish.
T4 dropped the labels and left the BUBBLE carrying the speaker distinction alone — but the
bubble is `--field-bg` on a `--border` outline, near-invisible in some themes. On a
low-contrast theme the transcript could read as one undifferentiated voice, which is
exactly the failure D6 set out to avoid. Side is unmissable in every theme, at every
contrast, and costs no chrome.
Three decisions, each with a way to get it wrong:
- `align-items`, NOT `text-align`. The bubble is what moves; the prose inside it stays
left. `text-align: right` looks identical on a one-line message and is unreadable on a
three-line one — the suite fails on it.
- The bubble HUGS its content, so "Yes" is a 47px bubble and a pasted stack trace is a
wide one. The shape of a turn now carries what the label used to spell out.
- Capped at 85%, not 100%. At 100% a long question fills the measure, reads as a
full-width block again, and the side cue disappears when the transcript is densest.
Measured in headless Chrome at a 680px column, against develop:
before after
short bubble ("Yes") 680px 46.9px, flush right
long user turn 680px 578px — exactly the 85% cap
assistant 680px left 680px left (unchanged)
text-align in bubble start start
Tint stays as the secondary cue rather than being dropped: side alone would fail on any
surface that reflows the log to one column.
Guards, each bypass-verified by reverting the fix:
- alignment dropped; text-align:right substituted for align-items (the trap)
- the assistant pushed right too, which erases the asymmetry that IS the cue
- the bubble no longer hugging; the cap removed; the cap raised to 100%
- row direction, which would put the checkpoint control beside the bubble
T3 (code surfaces) is now the only slice of the plan still outstanding.
27 tests in webviewCss, 32 suites green.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the LevelCode AI chat webview transcript styling so user turns are right-aligned bubbles while assistant replies remain left-aligned prose, restoring an unambiguous speaker cue across themes (especially low-contrast ones) after T4 removed visible role labels.
Changes:
- Add CSS rules to right-align
.msg.uservia flex layout and cap user bubble width while keeping inner text left-aligned. - Add regression tests that enforce the “align-items, not text-align” rule, ensure assistant stays left, and verify the bubble hugs content with a percentage cap.
- Document the rationale and measurements for the T6/D8 “side cue” decision in
docs/CHAT-TYPOGRAPHY.md.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| extensions/levelcode-ai/media/chat.html | Adds the T6 transcript CSS: .msg.user becomes a right-aligned flex column; user bubble uses width: fit-content and max-width: 85%. |
| extensions/levelcode-ai/test/webviewCss.test.js | Adds CSS-level regression tests guarding alignment asymmetry, forbidding text-align: right, and enforcing “hug content + capped width”. |
| docs/CHAT-TYPOGRAPHY.md | Adds D8/T6 design notes and updates the slice status narrative to reflect the new primary speaker cue. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
From the reference, spotted after T4 landed: in the Claude Code console your messages are right-aligned bubbles and the replies are left-aligned prose.
This is the half T4 was missing, and it closes a risk T4 opened rather than adding polish. T4 dropped the labels and left the bubble carrying the speaker distinction alone — but the bubble is
--field-bgon a--borderoutline, which is near-invisible in some themes. On a low-contrast theme the transcript could read as one undifferentiated voice, which is exactly the failure D6 set out to avoid.Side is unmissable in every theme, at every contrast, and costs no chrome at all.
Three decisions, each with a way to get it wrong
align-items, nottext-align. The bubble is what moves; the prose inside it stays left-aligned.text-align: rightlooks identical on a one-line message and is unreadable on a three-line one. The suite fails on it.The bubble hugs its content.
"Yes"is a 47px bubble; a pasted stack trace is a wide one. The shape of a turn now carries information the label used to spell out.Capped at 85%, not 100%. At 100% a long question fills the measure, reads as a full-width block again, and the side cue disappears exactly when the transcript is densest.
Measured, not eyeballed
Headless Chrome, computed styles, 680px column, against
develop:"Yes")text-aligninside the bubblestartstart.ckwrap(checkpoint control)Tint stays as the secondary cue rather than being dropped: side alone would fail on any surface that reflows the log to a single column.
Guards
Each bypass-verified by reverting the fix:
text-align: rightsubstituted foralign-items(the trap)flex-direction: row— puts the checkpoint control beside the bubbleOne of these (
row) initially read as a miss:flex-direction: columnappears several times in the stylesheet, so my patch hit the wrong rule. Re-run against the full selector, it fails correctly.T3 (code surfaces) is now the only slice of this plan still outstanding. D8 wasn't in the original decomposition — it came from looking at the reference again after T4, which is the argument for shipping slices small enough to look at.
27 tests in
webviewCss, 32 suites green.