Agent chat: a streaming reply follows Reduce Motion when it turns on mid-reply
Fixes an internal report: a streaming reply that mounted with Reduce Motion off kept pacing its reveal and fading its newest words after Reduce Motion turned on, until the row remounted. The stylesheet had already switched.
Cause
useStreamReveal read prefers-reduced-motion once, into a ref, when the row mounted. StreamReveal copied that value into a readonly field in its constructor. Nothing listened for change, so fixing only the ref would still have left advance() pacing.
Change
StreamReveal.setReduceMotion(on): the field is no longerreadonly. Turning it on shows everything received.useStreamRevealadds onematchMediachangelistener per mounted row, and removes it on unmount. When Reduce Motion turns on, it cancels the row's pending reveal frame, shows the whole reply in that commit and clears the fading steps (.cv-fresh). Later text then shows whole as it arrives, the same as in a row that mounted with Reduce Motion on. Turning it off paces later text again.- Unchanged: row identity, the defaults and the mount-time behaviour. No new per-token work: the listener runs only when the system setting changes.
Test
RevealedMarkdown.test.tsx, "turning Reduce Motion on mid-reply shows the whole reply and stops the reveal". It mounts a row with Reduce Motion off and paces three frames of a long reply. Then it switches the stubbed matchMedia to reduce and checks:
- the whole reply shows;
- no
.cv-freshspan is left; - no reveal frame is pending;
- a later delta shows whole in one frame with no fade;
- unmounting removes the listener.
Red/green with bun test src/agent-session/acpmux/conversation/RevealedMarkdown.test.tsx through cmux-ci test:
-
red at the test-only commit
3eab9f1: the new test fails when Reduce Motion turns on, with the reply cut off mid-text (run 40982179853); the other 9 pass. -
green at the fix, merged with base,
e5ea1e9: 10/10 pass, along withtest/streaming-text-frames.test.ts(run 41253723297). That run's one red,chromium: a followed reply rises line by line without jumps(-32.5 against a -25.75 floor), is a flake that also happens on base code. On the same runner it passed 3/3 at this head and failed 1/3 with base'sRevealedMarkdown.tsxandstreamReveal.ts, with the same -32.5. -
A first Astra review at
7f5680bblocked with a P2: text that rendered but whose frame was cancelled before the reveal read it leftStreamRevealbehind what showed, so turning Reduce Motion off again could shrink the reply.bd4b2b8adds a red test for it ("Reduce Motion on then off before a frame keeps what shows when later text arrives": the shown length dropped from 1974 to 154, run 41260981611).f20e8fefixes it:setReduceMotion(true, text)takes in the latest text before it flushes. -
green at
f20e8fe: 11/11 pass (run 41266926949).
Review: Astra (gpt-6-astra, high) gave VERDICT: SHIP f20e8fe574b404c95bc0e32a4a2edde0b21e046b, with no P1, P2 or P3 findings.
Reds at this head: nightly-guards / release-notary ("Test What's New highlights and release notes") and its Guard status. The same steps fail on base's latest guard run 41262022316 at a2a65690, and this PR changes only the three webview files above.
UI: no visual change with Reduce Motion off. With it on, the reply shows whole at once, as a row that mounted under Reduce Motion already does.
Agent session: agent session
š¤ Generated with Claude Code