[cx-ncc.112.66, cx-ncc.112.74] cmux NEXT agent chat: the rail's lit band glides at rest, shows at 75%, and stays lit on hover
Leo-ask: ask-50f889c053
Leo-ask: ask-8dbc4a81e1
Takes back #22228: it lit the prompts on screen at 60% and dimmed them back to rest while the pointer was on the rail, so the band barely showed where the reader was. This PR lights them at 75% and keeps them lit on hover. #22228's rail, geometry, fisheye, card, click and scrub are unchanged.
This PR carries over the parts of #24065 that #24058 (50826464) does not cover. #24058 already restored the compact rail as the default and made its band reach the bottom ticks (railScrollTop). It also keeps the band followed with the pointer on the rail (followPointer). This PR builds on that code. The full-height map (#22784) stays selectable from cmux.experiments, as #24058 left it. #24065 is closed in favour of #24058 plus this PR.
What Leo said
On the nightly, the agent chat's left-edge prompt rail (#22228, the Codex rail) "felt short". He explained: "it wouldn't show the highlighted bottom text where I was scrolling at the bottom, and it just didn't go to the bottom. It didn't show the bottom bits being highlighted." About the full-height map: "Why did you turn it into a whole mini map? ... I didn't want the mini map." From #24065's notes on the band's motion (Leo, 2026-10-21): "the wave didn't look good enough".
Change against #24058
| #24058 (base) | This PR | |
|---|---|---|
| Lit band brightness | 60% over rest at 40% | 75%, through --acpmux-minimap-lit |
| Band with the pointer on the rail | dimmed back to rest | stays lit beside the fisheye |
| Band moving at rest | rows flick from rest to lit | brighten and dim over 120 ms (--cmux-motion-micro) |
Hover, scrub, data-reduce, prefers-reduced-motion | switch at once | still switch at once |
| Keyboard focus, the pointer leaving the rail | switch at once | still switch at once: the active tick never glides, and a commit that changes the active row, hover or scrub marks the rail data-snap |
Full-height map (full arm) | as #24058 left it | unchanged: the glide is scoped with :not(.acpmux-scrollmap) |
Default arm, railScrollTop, followPointer, the bottom fix | #24058 | unchanged |
threadMinimap.css: a@media (prefers-reduced-motion: no-preference)block gives the rail at rest acolortransition on ticks andtransform, opacityon bars. The lit bar readsopacity: var(--acpmux-minimap-lit, 0.75). The two[data-hovering] … [data-tone="current"]rules that dimmed the band are gone.lit.experiment.ts(new, registered):thread-minimap-litwith armslit-60,lit-70,lit-75(default) andlit-85.ThreadMinimapreads the arm once per pane and sets--acpmux-minimap-liton the rail. Dogfood:{"thread-minimap-lit":"lit-60"}incmux.experiments.
Timers and cleanup: this PR adds no timer, observer or animation loop. Each glide is a CSS transition that ends by itself after 120 ms. A hovered, scrubbed or Reduce Motion rail runs none. No new per-token work: the arm is read once per pane in a useState initializer.
Versions (gallery)
New entry agent-pane.thread-minimap-lit: 18 or 70 synthetic prompts (Prompt N: check the next step of the plan), with states mid-thread, at-the-end and hovered, and the four thread-minimap-lit arms side by side in the compare view.
Stills: the rail strip of each gallery frame at 2x, taken with Playwright's headless Chromium from the gallery host's builds. "Before" is base ea5f81f0 and "after" is this head, 61de4e98. Each frame waits for data-gallery-ready, then 600 ms for the transitions to finish. The computed bar opacities read in the same frames are: rest 0.4 everywhere; lit 0.6 before and 0.75 after; with the pointer on the rail, lit 0.4 before (dimmed) and 0.75 after; the hovered tick 1.
Before / after (dark, light):
Pointer on prompt 9 of 18, band on prompts 15 to 18. Before: the band drops back to rest. After: it stays lit.

At rest mid-thread:

Seventy prompts at the bottom of the chat (#24058's fix, now lit at 75%):

Versions: lit at 60% (#22228's, the before), 70%, 75% and 85%; dark, then light:
At rest mid-thread:

At the end of a 70-prompt chat:

Pointer on prompt 3, band on prompts 4 to 7:

Pick: 75% (the default). At 60% the band is a soft step over rest, most of all in light mode. At 85% in light mode the band is nearly as dark as the hovered tick, so the row under the pointer stops standing out. 75% reads as lit in both schemes and stays clearly under the hovered tick. The other arms stay selectable from cmux.experiments.
Gallery: agent-pane.thread-minimap-lit, agent-pane.thread-minimap/rest, agent-pane.thread-minimap/long-chat, agent-pane.thread-minimap/seventy-prompts-bottom
- Live before/after of every state, base and this branch: https://cmux-lawrences-mac-mini.tail137216.ts.net:18796/compare/tp-minimap-band-glide/?entry=agent-pane.thread-minimap (tailnet only)
- The gallery advisory run's own PNGs stay in its artifact,
gallery-advisory-24526-<head>.
Tests
webviews/test/thread-minimap-default-wave.test.tsx adds:
- the lit band ships at 75%, and
lit-60andlit-85reach the rail's--acpmux-minimap-lit(rendered throughVirtualTranscript); - the lit bar reads
var(--acpmux-minimap-lit, 0.75), and no rule dims the rail's band under[data-hovering]; - at rest the bar transitions
transformandopacity, and the tick transitionscolor, over--cmux-motion-micro, both inside the no-preference query, and never on an active tick or adata-snaprail; - focusing a tick, and leaving it, marks the rail
data-snap, and the next band move from the scroll clears it (rendered throughVirtualTranscript).
thread-minimap-motion (browser lane) reads the bar's transition at rest: exactly transform, opacity, each 0.12 s with no delay.
Review: Codex (gpt-6.1-sol, xhigh) blocked 61de4e98 on focus and pointer-leave fading, and on the motion test's loose pattern; b6762ca4 fixes all three.
Observed / Not run
- Observed on huge-blue (
scripts/ci/run-webviews-tests.sh, bun 1.4.2): 14 of 15 files pass: thread-minimap default-wave, bottom, rail, current, feel, stream, tiny, room and card-glass, plus gallery agent-pane-entries, manifest, play-names and touched-rank. The 15th,gallery-coverage, fails its two cover checks with the same lists on base, none of them this PR's.vp lintandvp fmt --checkare clean on the touched files.typecheckreports 3 errors, all inthread-minimap-stream.test.tsx, which this PR does not touch (base). - Not run locally:
thread-minimap-motion's browser lane (CI only).
Changelog
- Improved: the agent chat's prompt rail lights the prompts on screen more clearly, keeps them lit while you point at the rail, and glides the lit band as you scroll.
Webview only; no Swift change.
Agent session: cosmic-gray
🤖 Generated with Claude Code