Skip to content

Fix velocity hand-off for hardware-accelerated springs - #3902

Open
mattgperry wants to merge 1 commit into
mainfrom
claude/project-thread-teqyqt-spring-velocity
Open

mattgperry wants to merge 1 commit into
mainfrom
claude/project-thread-teqyqt-spring-velocity

Conversation

@mattgperry

Copy link
Copy Markdown
Collaborator

Requested by Matt · project thread

Before: when a spring runs as a WAAPI animation (for example opacity or filter) and interrupts a moving value, it started at the wrong speed. When it moved towards a lower value, it started in the wrong direction. For small ranges like opacity, the inherited velocity was almost lost.

After: the WAAPI spring starts with the same velocity, and in the same direction, as the same spring on the main thread.

How: createGeneratorEasing builds the spring over 0 to 100 and samples it into a linear() easing, but it passed the velocity in the value's own units. It now scales velocity by 100 / (target - origin). Non-numeric keyframes (colours, filters) parse to NaN and keep the velocity as before.

Tests: new create-generator-easing.test.ts. It fails on main (progress went forward when the velocity pointed away from the target) and passes now. motion-dom Jest and framer-motion test-client pass.

Size budget: this adds about 35 B gzip, which takes the animate scenario to 18,824 B (budget 18,800) and useAnimate to 19,169 B (budget 19,150) in yarn size --check. I did not raise the budgets in dev/inc/size-budgets.json, so measure will fail until you decide on that.

Found while prototyping in #3898 and #3900.

🤖 Generated with Claude Code

https://claude.ai/code/session_015HkhHt5hFXd2GyAsSEc2tv


Generated by Claude Code

createGeneratorEasing builds a spring over 0 to 100, but passed it the
velocity in the value's own units. An accelerated spring that interrupts
another animation therefore started with the wrong speed, and, when moving
towards a lower value, in the wrong direction. Scale velocity by
100 / (target - origin).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015HkhHt5hFXd2GyAsSEc2tv
@mattgperry mattgperry self-assigned this Oct 6, 2026

Copy link
Copy Markdown
Collaborator Author

ci/circleci: measure failed, as the PR description expected. Locally, yarn size --check puts animate at 18,824 B against an 18,800 B budget and useAnimate at 19,169 B against 19,150 B. The fix adds about 35 B gzip. I haven't raised the budgets in dev/inc/size-budgets.json myself, so this check stays red until you decide whether to raise them (for example to 18,850 B and 19,200 B).


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants