Skip to content

Agent chat: opening or closing Worked for slides the rows below and fades its steps in or out - #24050

Merged
teamleaderleo merged 25 commits into
feat-cmux-nextfrom
tp/fold-animation
Oct 23, 2026
Merged

teamleaderleo merged 25 commits into
feat-cmux-nextfrom
tp/fold-animation

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

Leo-ask: ask-a5c1976d1c
Leo-ask: ask-d974edac49
Leo-ask: ask-c07aebfca2
Leo-ask: ask-0bfebc52fd

Leo: "and we shuold also have some animation for collapsing and expanding" (the agent chat's transcript folds), and: "these situations when collapsibles get expanded i said earlier last night lawrence was talking about how it shouldnt move your scroll or whatever just expand the area at the bottom and you're in the same place... also this current one seems to shift the expandable area away also these all need animations for expand and collpase!", and: "and thne there were a few animations that didnt quite work for collapsing and expanding wrt tool calls and stufff".

What #23093 already covers (merged 2026-10-21): tool groups ("Ran 4 commands ›"), tool, command and MCP rows, settled runs and thoughts open and close with the shared fold (fold.ts). The body's height and opacity animate over --cv-fold-duration (the host's move token, about 180 ms; 0 under Reduce Motion or with cmux animations off), the chevron turns on the same token, and a click on a button.is-toggle holds that line in place.

Scope: motion and anchoring only. This PR doesn't decide what goes inside a "Worked for" fold. Leo's takeaway rule lives in the shared turns.ts function that tp/fold-interim-messages owns (#24300). This PR doesn't touch turns.ts.

Split to stay under 800 lines. This PR is the shared primitive and every in-row collapsible. The "Worked for" and subagent-group row motion (whole virtual rows sliding and fading, turnFold.ts) follows in its own PR once this one lands.

What this PR does

  1. One shared collapsible, useAnchoredCollapse (conversation/useAnchoredCollapse.ts): useAnchoredCollapse({ defaultOpen?, open?, onOpenChange?, animates? }) -> { open, present, toggle, setOpen, headerRef, bodyProps }.
    • The header stays on its pixel and the body grows or shrinks below it, on the shared fold.
    • Inside the transcript, the header sends a bubbling cmux:anchored-collapse event that VirtualTranscript answers with the same hold cmux NEXT: expanding a tool call or thought animates and never moves your view #23093's click path uses. Keyboard toggles, and headers that are not button.is-toggle, are held too.
    • Outside the transcript, the hook corrects the nearest scroller itself on each frame until the fold ends.
    • Tool groups, tool, command and MCP rows, background task notes, thoughts and the one-file edited-files diff all go through it. agent-message-style adopts it for the agent-message card in its own PR.
  2. Show more / Show less on a long prompt now animate.
    • Show more holds the bubble's top, so the text grows below it, and the button rides the bubble's bottom edge instead of jumping.
    • Show less holds the button where it was clicked, and the text shrinks back above it.
    • A reversal midway starts from the drawn height, and unmounting cancels what plays.
  3. The audit fixes (frame strips below, every collapsible in Chromium and WebKit):
    • The one-file edited-files diff appeared and vanished in one frame. It now goes through the hook.
    • A fold whose body draws its content late (the diff, highlighted code) opened to the few pixels drawn at the click, then snapped to full height. useFold now follows the content as it grows: each larger size takes over from the drawn height for the time left. Its ResizeObserver stops when the fold ends, when another starts, or on unmount.
    • Show more and Show less had no animation at all.
    • Show less on a prompt several screens tall, with motion off, lost its hold. The row shrank under the old offset and the virtualizer unmounted it, taking focus with it. While a hold lasts, the row it holds stays in the mounted ranges, and when the hold moves the offset, the mounted rows take the new offset in the same frame.
    • Tool rows, command groups, MCP calls, thoughts, background task notes and agent-message cards: each header stayed within 0 px in both engines, with no element running two animations at once (table below).

Works with tp/fold-no-blank-space: this PR doesn't touch reportDrawn, placeRows or the row ResizeObserver.

Changelog

  • Changed: Opening or closing a long prompt's Show more and a one-file edited card's diff in agent chat now animates and keeps the clicked line in place.

Frame strips

These are synthetic gallery fixtures, captured with headless Playwright on the fleet at 760x640 in the dark theme. Each fold's token is slowed tenfold to 1800 ms so one fold yields 8 to 12 frames. Each strip shows the open, then the close. Each frame's label gives ms since the click, the clicked header's y offset (dy), and the number of running animations (DUP would mark an element running two at once). Head is bf316ac; the commit after it changes only the motion-off hold.

Kind Chromium head dy (open / close) WebKit head dy animations per element
Command group 0 / 0 0 / 0 1
Tool row 0 / 0 0 / 0 1
MCP call 0 / 0 0 / 0 1
Thought 0 / 0 0 / 0 1
One-file diff 0 / 0 (base: no animation) 0 / 0 1
Show more bubble top held; button rides the edge (base: no animation) same 1
Agent message card 0 / 0 0 / 0 1
Background task note 0 / 0 0 / 0 1

Show more's dy is the button's, which rides the bubble's growing edge by design. The gallery's prompt sits at the transcript's end, where closing lets the browser clamp the offset (the one documented exception, #23093). The browser test below checks Show less mid-transcript.

One-file diff, before (no animation; the diff appears and vanishes in one frame):
before diff chromium
After, Chromium and WebKit:
after diff chromium
after diff webkit

Show more / Show less, before (no animation):
before show more chromium
After, Chromium and WebKit:
after show more chromium
after show more webkit

The rest, after (Chromium; WebKit measured the same, table above):
after command group chromium
after tool row chromium
after mcp call chromium
after thought chromium
after agent message chromium
after background task chromium

Live side by side (tailnet): https://cmux-lawrences-mac-mini.tail137216.ts.net:18796/compare/tp-fold-animation/?entry=agent-pane.transcript

Observed / Not run

  • transcript-fold-anchor-browser.test.ts (Chromium) adds the following:
    • One test per collapsible kind (a thought, a tool call, a command group, Show more). Each opens and closes mid-transcript, and checks on every painted frame that the line stays within 1 px and that no element runs more than one animation.
    • A 400-line prompt's Show less with Reduce Motion keeps its button on its pixel.
  • PR CI's webviews job runs these. The fleet steps sat queued behind the suites label for more than 30 minutes, so I cancelled them.
  • Reviewed by Codex (gpt xhigh, via acpmux) over several rounds. The receipt is in a comment at the head.
  • CI reds that also fail on base:
    • cmux-next checks: "No fleet host names in gallery fixtures", from base files ShowcaseMachineNameTests.swift and ChatInspector.gallery.tsx.
    • cmux-next checks: "Checks job structure", from test_cmux_next_checks_workflow.py web-bundles. This PR touches no workflow.
    • Guard status and release-notary.
  • Not run: an app build (this is a webview-only change).

Agent session: cosmic-gray

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review 3a581d7: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr24050 -f ref=tp/fold-animation -f platform=macos -f backend_mode=local

Passes: CI passes on 3a581d784c.

CI passes on 3a581d784c (run 39929998813 attempt 1).

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); signatures are its SIGNATURES table. A machine verdict is the runner's fault, not this PR's; yours means the failing file is one this PR changes, also red on main that main's latest full suite fails the same way, seen on other PRs that it failed on another pull request's run lately.

red: cmux-next checks (god files, concurrency, crash safety, l10n); NEW: red check: Checks job structure (+2 more) is not red on the base 4654a98; do not merge until green; see lane-rules

Tour of 3a581d784c (run): no media. The tour did not run: only webview code changed (15 path(s)), which the gallery advisory run checks in Linux Chromium on the pull request (its artifact holds any captures); add the media-tour-mac label, then re-add media-tour, to tour it on a Mac.

Gallery before/after for 3a581d7: 16 states rendered, 8 images differ, 1660 more touched states not rendered. Images are in the run's artifact, not on this public PR.

gh run download 39929998345 -R manaflow-ai/cmux -n gallery-advisory-24050-3a581d784c02d7ac4e96c3707bd0ddea5764f21a (then read gallery-review.json)

States
State Theme Status Diff Picked by
agent-pane.background-task-note/on-call Apple System Colors changed 0.0124% own BackgroundTaskNote.tsx
agent-pane.background-task-note/on-call Apple System Colors Light changed 0.0119% own BackgroundTaskNote.tsx
agent-pane.background-task-note/lone Apple System Colors Light changed 0.0109% own BackgroundTaskNote.tsx
agent-pane.background-task-note/lone Apple System Colors changed 0.0076% own BackgroundTaskNote.tsx
agent-pane.background-task-note/ended Apple System Colors Light unchanged 0% own BackgroundTaskNote.tsx
agent-pane.background-task-note/ended Apple System Colors unchanged 0% own BackgroundTaskNote.tsx
agent-pane.background-task-note-open/collapsed Apple System Colors Light unchanged 0% own BackgroundTaskNote.tsx
agent-pane.background-task-note-open/collapsed Apple System Colors unchanged 0% own BackgroundTaskNote.tsx
agent-pane.background-task-note-open/failed-open Apple System Colors Light changed 0.598% own BackgroundTaskNote.tsx
agent-pane.background-task-note-open/failed-open Apple System Colors changed 0.531% own BackgroundTaskNote.tsx
agent-pane.background-task-note-open/completed-open Apple System Colors Light changed 3.07% own BackgroundTaskNote.tsx
agent-pane.background-task-note-open/completed-open Apple System Colors changed 0.79% own BackgroundTaskNote.tsx
agent-pane.background-task-note-open/stopped-open Apple System Colors Light unchanged 0% own BackgroundTaskNote.tsx
agent-pane.background-task-note-open/stopped-open Apple System Colors unchanged 0% own BackgroundTaskNote.tsx
agent-pane.chat-width/standard Apple System Colors Light unchanged 0% own App.tsx
agent-pane.chat-width/standard Apple System Colors unchanged 0% own App.tsx
agent-pane.chat-width/wide Apple System Colors Light unchanged 0% own App.tsx
agent-pane.chat-width/wide Apple System Colors unchanged 0% own App.tsx
agent-pane.chat-width/wide-blocks Apple System Colors Light unchanged 0% own App.tsx
agent-pane.chat-width/wide-blocks Apple System Colors unchanged 0% own App.tsx
agent-pane.composer-floats/scrolled-to-end Apple System Colors Light unchanged 0% own App.tsx
agent-pane.composer-floats/scrolled-to-end Apple System Colors unchanged 0% own App.tsx
agent-pane.composer-floats/composer-grown Apple System Colors Light unchanged 0% own App.tsx
agent-pane.composer-floats/composer-grown Apple System Colors unchanged 0% own App.tsx
agent-pane.docked-chat/new-chat Apple System Colors Light unchanged 0% own App.tsx
agent-pane.docked-chat/new-chat Apple System Colors unchanged 0% own App.tsx
agent-pane.docked-chat/after-turn Apple System Colors Light unchanged 0% own App.tsx
agent-pane.docked-chat/after-turn Apple System Colors unchanged 0% own App.tsx
agent-pane.docked-chat/working Apple System Colors Light unchanged 0% own App.tsx
agent-pane.docked-chat/working Apple System Colors unchanged 0% own App.tsx
agent-pane.docked-chat/typing-in-dock Apple System Colors Light unchanged 0% own App.tsx
agent-pane.docked-chat/typing-in-dock Apple System Colors unchanged 0% own App.tsx

Pick other states with a Gallery: entry.id, entry.id/variant line in the PR body.

@blacksmith-sh

blacksmith-sh Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Found 8 test failures on Blacksmith runners:

Failures

Test View Logs
/tmp/tmpqucwhh_y/summary-missing.json (live):/summary-missing.json (live): View Logs
/tmp/tmpxo8gslws/summary-fail.json (live):/summary-fail.json (live): View Logs
[tabs] debug.tab_switch timed 0 of 40 switches/
[tabs] debug.tab_switch timed 0 of 40 switches
View Logs
[tabs] debug.tab_switch timed 0 of 40 switches/
[tabs] debug.tab_switch timed 0 of 40 switches
View Logs
[tabs] the window draws no frames/[tabs] the window draws no frames View Logs
[tabs] the window draws no frames/[tabs] the window draws no frames View Logs
test_base_passes (main.NoticesPairTests.test_base_passes)/
test_base_passes (main.NoticesPairTests.test_base_passes)
View Logs
test_targets_outside_the_app_go_to_the_mac_canary (main.SwiftCanaryFleetCoverage.te
st_targets_outside_the_app_go_to_the_mac_canary)/
test_targets_outside_the_app_go_to_the_mac_canary (main.SwiftCanaryFleetCoverage.te
st_targets_outside_the_app_go_to_the_mac_canary)
View Logs

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 22, 2026
…redCollapse)

The header stays where it was clicked (held by the transcript, or by the hook's own scroll
correction elsewhere) while its body plays the shared fold. Tool groups, tool, command and MCP
rows, settled runs, background task notes and thoughts use it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Bead cx-r65q2 created for this PR by the cmux coordinator.

teamleaderleo added a commit that referenced this pull request Oct 22, 2026
…ithout moving the view

The card's line and its Details are anchored collapses (useAnchoredCollapse, the transcript's
shared hook from #24050): the line the reader clicked (chevron, plain sender name, Reply, or the
cut card) stays on its pixel while the card under it changes, inside the virtualized transcript.
Before, at the latest row the view followed the card's growth and the line jumped 235 px up.

A cut card slides open to its whole height and back (fold.ts playResize: height over
--cv-fold-duration, easing out); Details and its envelope fold in and out in height and opacity.
At once under Reduce Motion; Find opening a message for its match does not animate.

useAnchoredCollapse.ts, ANCHORED_COLLAPSE_EVENT and App.tsx's holdAsked listener are #24050's,
byte for byte, so this rebases onto it cleanly once it lands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16028-eee2-75a1-b075-2e4023976100&host=Air-Blue
teamleaderleo and others added 2 commits October 21, 2026 22:13
… no blank band shows under the rows sliding up

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…fold-animation

# Conflicts:
#	webviews/src/agent-session/acpmux/conversation/ThoughtRow.tsx
#	webviews/src/agent-session/acpmux/conversation/ToolGroupRow.tsx
#	webviews/src/agent-session/acpmux/conversation/ToolRow.tsx
teamleaderleo and others added 3 commits October 22, 2026 01:06
…ling mid-fold moves rows alike; Show more rides the bubble edge

Codex review of b0a7e8e:
- Another toggle (click or anchored-collapse event) settles the turn fold still playing first:
  its slides finish and its ghost copies go, so the new hold measures a line that stays put.
- Leaving the fold (time up, another chat) settles it too, so no ghost outlives a session switch.
- Turn fold positions are measured from the clicked line, not the viewport, so a reader who
  scrolls mid-fold scrolls every row alike instead of rows sliding against the scroll.
- A fold's own end timer only ends that fold.
- Show more keeps its resize animations, cancels them on a reversal and on unmount, and moves
  the button with the bubble's bottom edge instead of letting it jump to its final place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…test per collapsible kind

- Show less holds the button where it was clicked and the text shrinks back above it, drawn until
  clipped (the strip showed the text clamp at once inside a still-tall empty bubble).
- A placement pass that moves a row still sliding replaces its slide from where it is drawn, so a
  row runs one animation at a time (the strips counted two on subagent rows).
- Browser test: a thought, a tool call, a command group and Show more each open and close with
  the clicked line within 1 px and at most one running animation per element.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…e anchored fold

The audit strip showed it appear and vanish in one frame.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…de on as copies; no per-render id copy

Codex review of 63b3623:
- A click below a playing turn fold settles it, then moves the offset by however far that moved
  the clicked line, so the new hold keeps the line on the pixel it was clicked at.
- A row below the line that mounts mid-fold slides from where it was placed at the toggle, on the
  fold's own clock (a negative delay), so it moves with the rows around it.
- A row the open pushes past the mounted rows leaves a copy that slides on to its place instead of
  vanishing; a row the close hides still fades out.
- The fold reads row ids on demand and finds the toggled row from its last index, instead of
  mapping the whole transcript on every render while it plays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
teamleaderleo and others added 3 commits October 22, 2026 01:40
…d evicted rows keep their motion

Codex review of ca258cb:
- Each row below the line plays from its place at the toggle to its place now, on the fold's own
  clock: an element that mounts mid-fold (a scroll, a remount) joins part way instead of snapping
  or restarting, a revealed row's fade included.
- A row element that leaves the mounted rows mid-fold, including one mounted after the toggle,
  leaves a copy that goes on with the same motion from the same point; the copy goes when the
  row is drawn again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…rows to content that draws late

The PR was past the 800-line rule (1233 lines). This PR keeps the shared anchored collapse and
every collapsible that goes through it. The Worked for and subagent row motion (turnFold.ts, its
tests and gallery variants) moves to its own PR, on top of this one once it lands.

The audit's diff strip showed a one-file card's diff open to the few pixels drawn at the click,
then snap to its full height when the diff rendered. An open now follows content that draws late:
each larger size takes over from the drawn height for the time left. Its observer stops when the
fold ends, when another starts, or on unmount.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…he held offset in the same frame

Codex review of bf316ac: Show less on a prompt several screens tall, with motion off, shrank the
row under the old offset, so the virtualizer dropped it (and the hold and focus with it) before the
hold put the button back. The held row now stays in the mounted ranges while the hold lasts. When
the hold moves the offset, the mounted rows take it in this frame, as the composer lift does,
instead of waiting for the scroll event. A browser test covers a 400-line prompt with Reduce
Motion.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex xhigh): SHIP at a6a13b7

No blocker or major findings. The round-two fix addresses the motion-off Show less virtualization failure by retaining the anchor row and synchronizing scroll state before paint. The full diff and the surrounding code were reviewed; no tests or builds were run.

The earlier rounds of this review (Codex xhigh via acpmux, on a different model from the author) found these issues, all fixed at this head or moved out of this PR with the Worked for row motion:

  • headers drifting when a second fold started mid-slide;
  • rows sliding against a reader's scroll;
  • ghosts outliving a session switch;
  • Show more animations that were never cancelled;
  • virtualized rows snapping;
  • O(rows) work per render.

@teamleaderleo teamleaderleo added the ready-to-land Reviewed at this head; next-autoland merges it into feat-cmux-next when its only reds are base reds label Oct 22, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Orphaned: no activity for 13 h, and no lane holds a lease on it. The orphan sweep could not merge feat-cmux-next in: conflicts in webviews/src/agent-session/acpmux/conversation/CommandRow.tsx, webviews/src/agent-session/acpmux/conversation/ToolGroupRow.tsx. Listed for a lane to resolve.

…mation

# Conflicts:
#	webviews/src/agent-session/acpmux/conversation/CommandRow.tsx
#	webviews/src/agent-session/acpmux/conversation/ToolGroupRow.tsx
@cursor

cursor Bot commented Oct 23, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot uses usage-based billing for this team and requires on-demand usage to be enabled.

A team admin can enable on-demand usage in the Cursor dashboard.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

cmux-next / cmux-next checks (god files, concurrency, crash safety, l10n) › Checks job structure is red on 9 of 14 fresh feat-cmux-next PR heads in the last 2:00:00, so it is most likely a base red, not this PR's. The base-reds lane has it; a base merge picks up the fix once it lands.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

cmux-next / cmux-next checks (god files, concurrency, crash safety, l10n) › No fleet host names in gallery fixtures is red on 9 of 14 fresh feat-cmux-next PR heads in the last 2:00:00, so it is most likely a base red, not this PR's. The base-reds lane has it; a base merge picks up the fix once it lands.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

cmux-next guards / nightly-guards / workflow-guard-tests / release-notary is red on 19 of 20 fresh feat-cmux-next PR heads in the last 2:00:00, so it is most likely a base red, not this PR's. The base-reds lane has it; a base merge picks up the fix once it lands.

jsdom (and any header in another document) rejects a CustomEvent made by
a different window, so the fold-motion and ThoughtRow tests never opened.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
teamleaderleo and others added 2 commits October 22, 2026 21:01
…a prompt mid-transcript

The harness page loads no string table, so labels render as keys and a
text match finds nothing; the latest command group can start open; and
the tall prompt is virtualized away until the view walks up to it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…mation

# Conflicts:
#	webviews/src/agent-session/acpmux/conversation/ToolRun.tsx
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

cmux-next / cmux-next checks (god files, concurrency, crash safety, l10n) › No new SwiftUI (macOS UI is AppKit) is red on 12 of 13 fresh feat-cmux-next PR heads in the last 2:00:00, so it is most likely a base red, not this PR's. The base-reds lane has it; a base merge picks up the fix once it lands.

teamleaderleo and others added 4 commits October 22, 2026 21:21
…e clicking

Rows that mount on the walk up are measured and shift the button, so a
single placement sometimes left it off screen and the click missed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…HTMLElement

A DOM with no global HTMLElement (the working-line tests' happy-dom) threw
from the no-listener path on every toggle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…and so does unmount

Two quick toggles with no transcript listening each started a frame loop
that moved the scroller, so their corrections added up and overshot.
Also says why a Find reveal opens without a hold.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
…mation

# Conflicts:
#	webviews/src/agent-session/acpmux/conversation/CommandRow.tsx
#	webviews/src/agent-session/acpmux/conversation/McpCallRows.tsx
#	webviews/src/agent-session/acpmux/conversation/ToolRow.tsx
@teamleaderleo teamleaderleo removed the ready-to-land Reviewed at this head; next-autoland merges it into feat-cmux-next when its only reds are base reds label Oct 23, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

rust workspaces / plan (changed Cargo workspaces) is red on 12 of 15 fresh feat-cmux-next PR heads in the last 2:00:00, so it is most likely a base red, not this PR's. The base-reds lane has it; a base merge picks up the fix once it lands.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

rust workspaces / rust workspaces is red on 16 of 17 fresh feat-cmux-next PR heads in the last 2:00:00, so it is most likely a base red, not this PR's. The base-reds lane has it; a base merge picks up the fix once it lands.

Show less now animates the text back to its first lines, so the clamp is
read after the bubble's animations finish, not the frame aria-expanded flips.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex xhigh, correctness first): SHIP at 3a581d7

  • Codex xhigh (codex exec --sandbox read-only on cmux16, diff-only, no checkout) reviewed the full gh pr diff at ad0ab9e and said SHIP. An earlier round at 430b2cd said HOLD over two points. First, rapid toggles could stack the fallback scroll corrections; that's fixed: a toggle or an unmount now cancels the running correction. Second, Find reveals don't hold their header; that's kept on purpose and documented, because a hold would undo Find's scroll to its match. A delta review of the final commit, which is test-only (the long-prompt test now waits for Show less's fold before measuring), said SHIP at 3a581d7.
  • The merges of base resolved conflicts in imports only (CommandRow, McpCallRows, ToolRow, ToolRun), and the reviewer checked them.
  • Ran on huge-blue at 3a581d7:
    • transcript-fold-anchor-browser: 8/8
    • fold-motion: 15/15
    • fold-no-blank-space-browser: 1/1
    • worked-fold: 9/9
    • ThoughtRow: 30/30
    • transcript-working-line: 12/12
    • agent-pane-long-prompt: 1/1
    • Lint and format are clean on the changed files. tsc reports errors only in QuestionCard.gallery.tsx and home-cloud-rows.test.ts, which this PR doesn't touch.
  • Other reds at the previous head are not this PR's:
    • composer-type-scale (nt-style-input)
    • agent-pane-peer-chat
    • agent-pane-no-capsules
    • popup-one-hairline (.acpmux-omni)
    • rust workspaces, guard status, release-notary, and the cmux-next checks host-name and job-structure checks, which are also red on base.

@teamleaderleo
teamleaderleo merged commit 6ef5b51 into feat-cmux-next Oct 23, 2026
122 of 127 checks passed
@teamleaderleo
teamleaderleo deleted the tp/fold-animation branch October 23, 2026 09:19
@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

teamleaderleo added a commit that referenced this pull request Oct 23, 2026
…the rows below and fades its steps (#24514)

* Agent chat: Worked for and subagent groups open and close in motion, the rows below sliding and the steps fading

Leo (2026-10-21): "these all need animations for expand and collpase!" Opening Worked for inserts
whole virtual rows, so the in-row fold can't size it. turnFold.ts plays it instead:
- rows below the clicked line slide from where they were drawn (a FLIP on translate);
- the steps it reveals fade in;
- on close, inert copies of the hidden steps fade out under the rows sliding up.
Every row plays on one clock, so rows that mount or unmount mid-fold keep their motion. A second
toggle settles the playing fold first and keeps the clicked line on its pixel. Nothing runs with
animations off or under Reduce Motion.

Reviewed in three Codex xhigh rounds while it was part of #24050.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray

* Turn fold: an ended fold lets go of its rows, and unmount settles a playing one

When its timer ended a fold, the transcript still pointed at it, with the
rows as placed at the toggle, the tracked row elements and animations, until
the next render. Unmount now settles a playing fold too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray

* Turn fold: a pass runs only when its rows are placed again, never per streamed token

A MutationObserver started at the toggle runs the pass when the thread's
row elements mount or unmount or a row's placement (style, index) changes;
a token streamed into a row changes neither. It disconnects when the fold
ends (its timer, the next toggle, another chat, unmount). A render only
checks in O(1) whether the fold is over. The turn-fold tests move into
transcript-fold-anchor.test.tsx, which has the same transcript setup, and
a new one counts passes while tokens stream.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray

* turnFold.ts: shorter comments

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16030-bf28-7072-b1f6-b83bbd0beacc&host=cosmic-gray

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
teamleaderleo added a commit that referenced this pull request Oct 26, 2026
… card

#24050 landed, so App.tsx, foldAnchor.ts and useAnchoredCollapse.ts are base's. The
normal-mode card now holds its line through base's collapse (toggle, cut card, Show
more), resizes its text with playResize, and folds Details; Minimal Mode is unchanged.

Agent-Session: https://cmux.com/deeplink/agent?id=aid-26b034d85e005a5da1d0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-26b034d85e005a5da1d0
teamleaderleo added a commit that referenced this pull request Oct 26, 2026
…ithout moving the view (#24085)

* Agent pane: another agent's message opens below its line, animated, without moving the view

The card's line and its Details are anchored collapses (useAnchoredCollapse, the transcript's
shared hook from #24050): the line the reader clicked (chevron, plain sender name, Reply, or the
cut card) stays on its pixel while the card under it changes, inside the virtualized transcript.
Before, at the latest row the view followed the card's growth and the line jumped 235 px up.

A cut card slides open to its whole height and back (fold.ts playResize: height over
--cv-fold-duration, easing out); Details and its envelope fold in and out in height and opacity.
At once under Reduce Motion; Find opening a message for its match does not animate.

useAnchoredCollapse.ts, ANCHORED_COLLAPSE_EVENT and App.tsx's holdAsked listener are #24050's,
byte for byte, so this rebases onto it cleanly once it lands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16028-eee2-75a1-b075-2e4023976100&host=Air-Blue

* Agent pane: Reply opens a message without holding its line, so the editor is in view

Holding the line while Reply opened a long message left the focused editor below the view at the
latest row. Reply now opens the card as before (the view follows the editor), still animated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16028-eee2-75a1-b075-2e4023976100&host=Air-Blue

* Agent pane: a cut message's card never shrinks a frame as it opens

Show more leaves at once while the text slides from its cut height, so the card
was a button shorter for one frame; at the latest row that pulled the transcript's
end, and the held line, 24 px up. The text now starts at the height that keeps the
card as tall as it was drawn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-26b034d85e005a5da1d0

* Agent pane: Find opening a closing message stops its slide

A card sliding shut that Find opened again kept playing its resize, clipped
until it ended and then snapped open. Find's open now cancels it (fold.ts
cancelResize). From the review of #24085.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-26b034d85e005a5da1d0

* Agent pane: Minimal Mode's Details opens and closes at once, as before

The envelope's fold ran in Minimal Mode too, animating Details and leaving the
envelope mounted while it closed; #25002 shows and hides it at once there. The
fold now runs only out of Minimal Mode. From the review of #24085.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-26b034d85e005a5da1d0

* Agent pane: rows below a message's card follow its slide before paint

playResize now marks its row as folding (heightFoldInFlight), as useFold does, so
the transcript places the rows under a sliding card synchronously instead of a
frame late. A long message with no Details had nothing else marking it. From the
review of #24085.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-26b034d85e005a5da1d0

* Agent pane: Find stops a message's slide even when it is already open

Find's reveal cancelled the text's resize only through the [open] effect, so a
card the reader had just opened kept sliding when Find landed on it. The reveal
now cancels it directly. From the review of #24085.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-26b034d85e005a5da1d0

* Agent pane: a cancelled message slide lets go of its clip at once

cancelResize cleared the text's overflow only from the animation's cancel
event, which comes after the next paint, so Find opening a sliding card could
show it clipped for a frame. It now clears it before cancelling. From the
review of #24085.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-26b034d85e005a5da1d0

* Agent pane: each display mode folds its own message box

Minimal Mode's card and the normal card's Details row shared one collapse, so
switching Minimal Mode mid-close moved its ref to a new box while the old fold
played on, and the whole card showed under the preview until it ended. Each
mode now has its own collapse; the one not drawn changes at once. From the
review of #24085.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-26b034d85e005a5da1d0

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant