Ship the side-highlight prototype: a rail means nesting now - #2404
Merged
Merged
Conversation
jonathanKingston
force-pushed
the
claude/copse-threads-prototype-c5c83c
branch
from
September 6, 2026 03:43
90c49f1 to
c93fbe0
Compare
Contributor
🖥️ PR preview
|
jonathanKingston
temporarily deployed
to
github-pages
September 6, 2026 03:49 — with
GitHub Actions
Inactive
Contributor
Reference screenshots ready for reviewReview GitHub’s image diffs in screenshot PR #2572. Rendered for If this source branch moves, a later successful render closes the stale review PR and replaces this link. |
`prototypes/side-highlight` inventoried ten accent rails across six stylesheets doing three unrelated jobs — containment in the transcript, selection in the sidebar, nesting under a tool card — and proposed "M, the mix", split by what each block *is* rather than by what it looks like. This implements it. Only nesting keeps the bar, which is literally what a nesting guide depicts; `accent-rails.test.ts` now holds that list closed. Containment becomes a plate, in two materials (base.css): - **Flat** — GitHub alerts and blockquotes. Prose the agent wrote is part of the answer, so it gets a plain surface and the hue moves to the title. These are styled by `@copse/streaming-markdown`, so markdown.css overrides at the package's own specificity and wins on source order; no upstream change. - **Hatched** — thinking, review, comparison. Copse annotating its own turn, and a texture says so without spending a fourth hue or a fourth shape. It degrades to the flat plate under `prefers-reduced-transparency` and `prefers-contrast: more`. The VNC pane takes the gutter instead: a separate pane whose status hue has to survive on one line, where a plate would just box three of them. Selection — chat rows, Settings nav, VNC tabs — becomes the full-bleed fill plus weight. Answering the prototype's open questions: - **Moiré is settled by the number.** 8 is a multiple of 4, so at every quarter-step display scale the hatch period lands on a whole count of device pixels and there is no beat frequency. The pitch is load bearing. - **Two new hues.** Five alert kinds need five, and the palette had three. `--info` and `--important` join the semantic tokens with derived light values. `--important` is pushed bluer than a true violet so it does not read as the pink accent; a user whose accent *is* purple still collapses that, which is written down rather than fixed. - **Callout glyphs are solid**, the only filled shapes in an outline set, with distinct silhouettes so the kind reads before the hue. Their optical-centring nudges are baked into each mask's viewBox — measured once by the prototype, not recomputed at runtime. The tuning lives in base.css but the colour is mixed at each use site, because a custom property is substituted where it is *declared*: one holding the whole `color-mix(… var(--sev) …)` freezes the root's grey into its computed value and inherits that grey everywhere, whatever each block sets --sev to. Every plate came out the same neutral, and a screenshot is not how you catch that — the new `callout-surfaces` e2e spec is, and it did. `.thread-proposal` (#2334) landed after the prototype's inventory and keeps its rail, allowlisted with the reason: a standing offer is an *ask*, a fourth job the bar was not doing when this was surveyed. Worth revisiting deliberately. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CI's full e2e tier found what the stylesheet-level guard could not: four specs assert the old design directly, so removing the rails made them fail rather than pass. Each is repointed at what the surface means now, not just at a new number. - `conversation-visual-hierarchy` pinned review and comparison to a 2px left border, a zero radius and a fading `linear-gradient` wash. They take the hatched plate now, and the radius is the part a rail could never have had — it would have bowed around the corner. - `markdown-streaming-blockquote` used the rail's width as its proof that the stylesheet had reached a *pending* quote at all. That proof is the plate now: a filled background and a radius, plus an explicit `0px` border so the rail cannot creep back on the streaming path alone. - `thread-sidebar-selection` and `ui-polish` both asserted a rail — trailing on a chat row, leading on Settings nav. Both are the full-bleed fill plus weight, and in `ui-polish` the two now being *identical* is the assertion: one selection gesture wherever the list sits, where the old spec required them to differ. Unrelated: `thread-terminal-rename-archive` also failed on shard 8 with "expected renamed terminal label", a wait on the terminal tab's rename. It passes locally against this build and touches nothing this branch changed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
jonathanKingston
force-pushed
the
claude/copse-threads-prototype-c5c83c
branch
from
September 6, 2026 09:18
c93fbe0 to
c66defc
Compare
jonathanKingston
temporarily deployed
to
github-pages
September 6, 2026 09:20 — with
GitHub Actions
Inactive
jonathanKingston
marked this pull request as ready for review
September 6, 2026 16:13
One conflict, in `styles/global/markdown.css`, and it was two appends to the same end of file rather than a disagreement: this branch adds the callout plate and its glyph masks, `main` adds the light-theme `.hljs-*` palette (#2565, issue #2486). No shared selectors, so both are kept, ours first. `docs/ui-taste.md` merged cleanly but the two sides then said different things. #2565 added "carry a fill (--bg-selected) or a rail as well, so the signal survives both themes", and on this branch a rail no longer means selection at all. Reworded to name the fill alone and point at "A rail means nesting, and nothing else" — which sharpens rather than weakens #2565's point: with the rail gone, the fill's own contrast is the entire signal for a selected row. The two changes are otherwise complementary. #2565 rederived light's `--bg-selected` off `--accent-fill`, which is exactly the token this branch now leans on harder. `pnpm run check` passes on the merged tree (8733 tests, 0 failures), including the `light-contrast.test.ts` that arrived with #2565, and the five e2e specs that cover the changed surfaces pass against a fresh build. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
chore(e2e): review screenshots for #2404
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.
prototypes/side-highlight(#2350) landed as prototype files only — 3,138 lines ofworkshop, and nothing in
src/. Its inventory of ten accent rails still matched thesource line-for-line, so none of its proposal had been implemented. This implements
M — the mix, the design it proposed.
The design
The rail used to do three unrelated jobs, and looked the same doing all of them:
containment in the transcript, selection in the sidebar, nesting under a tool card.
One device serving three meanings is what made it read as repetition rather than as
signal. Only nesting keeps it, which is literally what a nesting guide depicts.
Alerts and blockquotes are styled by
@copse/streaming-markdown, so they areoverridden locally in
styles/global/markdown.css:renderer/main.tsimports thepackage's default.css before
global.css, so rules at the package's own specificitywin on source order. No upstream change was needed.
The prototype's open questions
when its period lands near an integer count of device pixels. 8 is a multiple of 4,
so at every quarter-step scale Windows offers (1.25×, 1.5×, 1.75×, 2×) the period is a
whole number of device pixels and there is no beat frequency. The pitch is now load
bearing;
base.csssays so where it is declared.wash comes up to the plate's weight, so commentary keeps a surface and loses only its
distinction from content.
--infoand--importantjoin the semantic tokens with derived light values.--importantispushed bluer than a true violet so it does not read as the pink accent — a user
whose custom accent is itself purple still collapses that, which is written down
rather than fixed (the fix is to derive
--importantaway from--accent).docs/ui-taste.mdnow states the house rule outright: filled marks transcript status,outline is chrome. That is also what scopes the two warning triangles rather than
retiring one. The optical-centring nudges are baked into each mask's
viewBox,measured once by the prototype and not recomputed at runtime.
For a reviewer
custom properties. A custom property is substituted where it is declared, so
--callout-platefroze:root's grey into its computed value and inherited that greyeverywhere — every plate came out the same neutral. A screenshot did not catch it; the
new
callout-surfacese2e spec did. The tuning now lives inbase.cssand the colouris mixed at each use site.
.thread-proposalkeeps its rail. It landed in Let the agent propose whole new threads #2334, after this inventory wastaken, and its rail marks a standing ask — a fourth job the bar was not doing when
the prototype surveyed it. Allowlisted with the reason rather than converted silently.
Worth deciding deliberately.
accent-rails.test.tsnow holds the list closed. It kept the "a rail never curves"contract and gained a second rule: a rail may only mean nesting. A trailing-edge
border is out of scope there, because that is how the app walls one pane off from
the next.
docs/ui-taste.mdcontradicted this in three places — "Accent rails never curve","Sidebar selections", and "Transcript status callouts", which used to forbid a tinted
block outright. All three are rewritten with the reasoning, not just the new rule.
Verification
pnpm run checkpasses end to end (8544 pass / 0 fail / 7 skipped).tests/e2e/callout-surfaces.e2e.tsseeds every affected surface onone screen and asserts the plate resolves per severity, the hatch actually hatches, the
selected row has neither border nor shadow, and all five glyphs are distinct — with
dark and light workbench screenshots.
color-mixover livetheme tokens, so they follow it without re-derivation.
check:screenshotsflags them,and the sanctioned path is the CI e2e candidate artifact — hence the
update-screenshotsandci-fulllabels on this PR.🤖 Generated with Claude Code