iOS: the team drawer and Jump to latest settle at once with Reduce Motion on

Merged
TE
7d ago
+285-9

Fixes two internal reports about NEXT iOS ignoring Reduce Motion:

  1. The team drawer always slid the card and parallaxed the sidebar on open and close, including the scrim dismissal and a released drag.
  2. Jump to latest from far up a transcript hid the whole transcript, waited 50 ms, faded it back over 150 ms and sprang the last screen over 400 ms.

They share one fix pattern, so they are in one PR: each controller reads UIAccessibility.isReduceMotionEnabled through a reducesMotion seam that the tests set, and settles at once when it is on.

Change

  • SidebarContainerViewController.settle: under Reduce Motion the drawer writes its end geometry at once and runs its settle steps in place, with no animator. Those steps were moved out of the animator's completion into didSettle: model progress; a closed card's square corners and hidden sidebar; VoiceOver's screen-changed post to the opened sidebar. Unchanged: the publish hit-testing and accessibility state, finger tracking during a drag (track writes the geometry per frame) and the animated path with Reduce Motion off.
  • ChatTranscriptController.scroll(to:animated:): under Reduce Motion an animated jump becomes an immediate offset change. Nothing hides the transcript and there is no fade or spring. The long-jump cut, the hidden frame (the stale-tile-over-the-composer workaround) and the spring are unchanged with Reduce Motion off, and the withoutReduceMotion… test still covers them.
  • AgentChatSurface.scrollToBottom's SwiftUI fallback (used when no UIKit scroller is attached) also skips its 0.35 s animation under Reduce Motion.

Tests

Each test reads the layers' running animations as well as the end point, because an animator writes the final model values at once and the end point alone would pass on the old code.

  • CmuxMobileShellTests/DrawerReduceMotionTests:
    • Open and close under Reduce Motion: the end geometry is set, no slide or parallax animation runs, and isOpen, progress, the hidden sidebar, corners and accessibility hiding are all set at once.
    • A released drag settles the same way, and the card follows the finger during the drag.
    • Control: with Reduce Motion off, the drawer still animates.
  • CmuxMobileAgentChatTests/JumpReduceMotionTests:
    • From the top of a 9000 pt transcript, Jump to latest lands on the bottom at once, with the transcript at alpha 1 and no animation.
    • Control: with Reduce Motion off, the long jump still animates.

Red/green (cmux-next-ios kit tests, iOS simulator):

  • red: the tests at this head with the fix commit (2e7f346d) reverted (490836485135), fleet step 708d4ad9 (cmux-next-ios-sim.sh test only=...JumpReduceMotionTests,...DrawerReduceMotionTests): 2 passed, 3 failed. aLongJumpLandsAtOnceWithTheTranscriptShown (the jump cut short to 7398 before 8272), openingAndClosingSettleInPlace and aReleasedDragSettlesInPlaceAndTheDragFollowsTheFinger (animation running, sidebar not hidden, corners 44) fail; both withoutReduceMotion… controls pass, so the oracle sees motion.
  • green at d320e909b302: fleet step a804f2ce, 5 passed, 0 failed. Kit CI: https://github.com/manaflow-ai/cmux/actions/runs/41017568819

The controls failed on the first push because of how the tests were set up, not because of the fix. UIKit animates from the last committed frame, and a layout pass still pending when the jump starts snaps a following transcript to the bottom. So the tests now commit the start position first. The jump test records every offset and opacity the jump writes through KVO, and it jumps through the same animated scroll that scrollTranscript(toContentY:) uses.

No capture: Reduce Motion end frames match the animated end frames; tests assert no animation runs

UI: with Reduce Motion off, nothing changes. With it on, the drawer and the jump land in their final place, so a before/after still shows the same end frame; the tests above record the difference in motion.

Agent session: agent session

🤖 Generated with Claude Code


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


Summary by cubic

Fixes NEXT iOS ignoring Reduce Motion: the team drawer always slid and parallaxed the sidebar on open and close, and Jump to latest from far up a transcript hid the transcript, faded it back, and sprang to the bottom. Both now settle at once when Reduce Motion is on, via a reducesMotion seam each controller reads.

Changes

  • Under Reduce Motion, SidebarContainerViewController writes the drawer's end geometry and runs its settle steps (corners, hidden sidebar, VoiceOver focus) in place with no animator; drags still follow the finger.
  • ChatTranscriptController turns an animated jump into an immediate offset change, keeping the transcript visible throughout.
  • The SwiftUI fallback in AgentChatSurface.scrollToBottom also skips its animation under Reduce Motion.
  • New tests verify no animations run and the end state lands at once; with Reduce Motion off, both behaviors are unchanged.