| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
…— T7
Two things, both from a side-by-side with the Claude Code console.
1. THE COMPOSER WAS NEVER IN THE COLUMN (D9)
T1 bounded the TRANSCRIPT and nothing else. #composer, #status and the four notice
bars are SIBLINGS of #log, not children, so none of them ever saw the cap: at editor
width the input was a ~1580px box sitting under an 820px conversation. Next to the
reference — where the composer sits directly under the text it answers — this was the
most obvious difference left, more than any type choice.
The measure moves from `#log` to `body`. That is the load-bearing part, not tidying:
a custom property declared on the log is invisible to the log's siblings, which is
exactly how the split arose.
Two consequences that are easy to miss:
- `--shell-x`. The shell insets by calc(100% - 2 * var(--shell-x)), the same value
#log pads with, rather than a bare width:100%. Without it the edges agree only
where the cap binds and out-dent by the log's padding everywhere else — including
every sidebar, which is the width most users are actually in.
- The runtime override moves too. chat.proseWidth was written onto #log; left there
it would resize the conversation and leave the composer on the stylesheet default,
reopening this same split but only for users who set it.
Measured in headless Chrome, composer vs prose edges, left AND right:
before (prose/composer) after
1600px 680 / 1584 (452px/side) 820 / 820 — delta 0.0
900px 680 / 884 820 / 820 — delta 0.0
800px 680 / 784 752 / 752 — delta 0.0
420px 476 / 484 476 / 476 — delta 0.0
The 420px row is the argument for --shell-x on its own: the sidebar was quietly
misaligned by 4px a side before this.
2. THE MEASURE WAS TOO NARROW (D1 revised, 680 -> 820)
At the same window width the reference's column is ~815px against our 680 — half the
available width where we used 41%. On a parameter chosen from first principles versus
the artefact we are explicitly trying to match, the artefact wins.
Stated honestly in the doc: 820px is ~130 characters at 14px, outside the print range
D1 already argues does not transfer, and ~815 is read off a screenshot — so 820 is a
round number near a measured one, not a transcription.
Guards, each bypass-verified by reverting the fix:
- composer/status dropped from the shell rule; shell uncentred; bare width:100%
- #log padding decoupled from --shell-x; --shell-x no longer widening at 760px
- the runtime override written back onto #log
- a second --prose-max declared on #log (two sources of truth for one column)
- the doc drifting from the shipped cap (the existing pin, still biting)
Also fixed a latent test bug this exposed: the rhythm test located its media block with
indexOf, so adding a second min-width:760px gate made it assert against whichever came
first in the file. It now finds the block by content.
29 tests in webviewCss, 32 suites green.
There was a problem hiding this comment.
This PR updates the LevelCode AI chat webview styling to match the reference layout more closely by making the entire panel (transcript + composer/status/notice bars) share one centered column, and by widening the shipped reading measure to 820px. It also updates the CSS test suite and the chat typography design doc to guard against regressions and keep documentation pinned to shipped values.
Changes:
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| extensions/levelcode-ai/media/chat.html | Implements the single-column shell layout, widens the measure to 820px, and moves runtime CSS var overrides to document.body. |
| extensions/levelcode-ai/test/webviewCss.test.js | Updates and adds guards to ensure the measure and shell column stay unified, and that runtime overrides target the correct element. |
| docs/CHAT-TYPOGRAPHY.md | Revises D1 to 820px and documents the new D9/T7 “shell column” rationale and exit criteria. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Sorry, something went wrong.
| const gates = [...css.matchAll(/@media \(min-width: 760px\)/g)].map((m) => m.index); | ||
| assert.ok(gates.length, 'the width gate is gone — the rhythm change would now hit the sidebar too'); | ||
| const at = gates.find((i) => css.slice(i, css.indexOf('\n }', i)).includes('#log {')); | ||
| assert.ok(at !== undefined, 'no min-width:760px gate contains the #log rhythm rules'); | ||
| const block = css.slice(at, css.indexOf('\n }', at)); |
| the composer ended up spanning the full panel while the prose sat in a 680px column. */ | ||
| --prose-max: 820px; | ||
| /* The horizontal inset shared by the log's padding and the shell column's width, so the composer's |
…ing the cap Both review comments on #75 were right. 1. THE GATE LOOKUP WAS STILL ORDER-DEPENDENT My earlier fix found the rhythm block by content instead of position, but still terminated the slice with `indexOf('\n }')`. The --shell-x gate is written on one line, so it has no `\n }` of its own — the search ran straight past it into the next multi-line block. Measured: for a rule whose body is 27 characters, the old search returned 238, i.e. it reached about nine times past the rule it was supposed to bound. It happened to resolve correctly, because the swallowed span did not contain `#log {`. That is luck of ordering, not correctness. Demonstrated by moving the one-liner gate to sit directly before the rhythm gate: under the old mechanism the FIRST gate's slice then contains `#log {`, so it selects the wrong gate and asserts against a span covering both — silently. Under balanced braces the same reorder still resolves to the right gate and all 30 tests pass. `blockAt()` matches braces, over a comment-stripped copy so a brace inside prose cannot throw off the count. 2. THE STYLESHEET COMMENT KEPT ITS OWN COPY OF THE CAP It still said 680px and "~116 characters" after the cap became 820. That is the third place this number has drifted and the only one nothing was watching — the existing pin covers CHAT-TYPOGRAPHY.md, not the stylesheet's own prose. Not synced: the comment must not carry the number at all, so it points at `--prose-max` instead. The two font measurements (8.13px per `ch`, 5.86px per average character) stay, because those are facts about the typeface rather than a decision that can be revised. Guards, each bypass-verified by reverting the fix: - the rhythm gate losing its padding, proving the block is located non-vacuously - the comment restating the current cap, and restating the OLD one (the reviewer's bug) - the comment no longer pointing at --prose-max - plus the reorder above, which the previous mechanism failed and this one survives 30 tests in webviewCss, 32 suites green.
|
Both right. Fixed in ffa5f0b. 1. The gate lookup was still order-dependentCorrect, and my previous fix only got half of it. I switched to finding the block by content but still terminated the slice with indexOf('\n }') — and the --shell-x gate is written on one line, so it has no \n } of its own. The search ran straight past it into the next multi-line block. Measured on the current file:
It reached about nine times past the rule it was supposed to bound. It happened to resolve correctly, because the swallowed span didn't contain #log { — luck of ordering, not correctness. Demonstrated by moving the one-liner gate to sit directly before the rhythm gate: OLD mechanism on the FIRST gate -> contains "#log {": True (picks the WRONG gate)
At that point it would select the wrong gate and assert against a span covering both, silently passing. Under balanced braces the same reorder still resolves to the right gate and all 30 tests pass. blockAt() now counts braces, over a comment-stripped copy so a brace inside prose can't throw off the count. 2. The stylesheet comment kept its own copy of the capAlso right, and this is the third place this number has drifted — the pin from #71 covers CHAT-TYPOGRAPHY.md, and nothing was watching the stylesheet's own prose. I took your second suggestion rather than the first: the comment doesn't carry the number at all now, it points at --prose-max. Syncing it would just set up the next drift. The two font measurements (ch = 8.13px, average character = 5.86px) stay — those are facts about the typeface, not a decision that can be revised. And it's guarded now: the comment must reference --prose-max, and must contain no length other than the two viewport widths (380px, 900px) that describe where the problem showed up. GuardsEach bypass-verified by reverting the fix:
30 tests in webviewCss, 32 suites green. |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
Two problems, both visible the moment you put the two apps side by side.
1. The composer was never in the column (D9)
T1 bounded the transcript and nothing else. #composer, #status and the four notice bars are siblings of #log, not children, so none of them ever saw the cap: at editor width the input was a ~1580px box sitting under an 820px conversation. Next to the reference — where the composer sits directly under the text it answers — this was the most obvious difference left, more than any type choice.
The measure moves from #log to body. That's the load-bearing part, not tidying: a custom property declared on the log is invisible to the log's siblings, which is exactly how the split arose in the first place.
Two consequences that are easy to miss:
Measured in headless Chrome. Composer vs prose edges, left and right:
The 420px row is the argument for --shell-x on its own: the sidebar was quietly misaligned by 4px a side before this, in the surface almost everyone uses.
2. The measure was too narrow (D1 revised, 680 → 820)
At the same window width the reference's column is ~815px against our 680 — about half the available width where we used 41%. On a parameter chosen from first principles versus the artefact we are explicitly trying to match, the artefact wins.
Stated honestly in the doc rather than smuggled in: 820px is ~130 characters at 14px, outside the print range D1 itself argues doesn't transfer — and ~815 is read off a screenshot, so 820 is a round number near a measured one, not a transcription. What makes it acceptable is that the reference demonstrably reads well at that width, and this column carries tables, file paths and fenced code, none of which wrap gracefully at 680.
Guards
Each bypass-verified by reverting the fix:
The last one fired for real during this change: the stylesheet moved to 820 and the pin failed until D1 was rewritten. That's the guard from #71 earning its keep.
One latent test bug this exposed
The rhythm test located its media block with indexOf('@media (min-width: 760px)'). Adding a second gate on the same breakpoint made it assert against whichever came first in the file — so it would have started passing or failing on rule order rather than on the thing it checks. It now finds the block by content.
29 tests in webviewCss, 32 suites green.