Skip to content

feat: arc path for layout and keyframe animations#3386

Closed
lochie wants to merge 23 commits intomotiondivision:mainfrom
lochie:lochie/arcs
Closed

feat: arc path for layout and keyframe animations#3386
lochie wants to merge 23 commits intomotiondivision:mainfrom
lochie:lochie/arcs

Conversation

@lochie
Copy link
Copy Markdown
Contributor

@lochie lochie commented Sep 26, 2025

Summary

Adds an arc transition option that makes elements travel along a curved Bézier path rather than a straight line.

Works with motion components, useAnimate, and layout animations via layoutId:

// Keyframe animation
<motion.div
    animate={{ x: 200, y: 100 }}
    transition={{
        arc: {
            amplitude: 1,      // how far the arc bulges (fraction of travel distance)
            peak: 0.5,         // where along the path the arc peaks (0–1, default 0.5)
            direction: "cw",   // "cw" | "ccw" | auto
            orientToPath: 0.5, //  rotates the element to follow the tangent of the arc path (boolean | number)
        },
    }}
/>

// Layout animation
<motion.span
    layoutId="indicator"
    transition={{
        layout: {
            arc: { amplitude: 1 },
        },
    }}
/>

// useAnimate
animate(el, { x: 200, y: 100 }, { arc: { amplitude: 1 } })
  • amplitude — how pronounced the arc is, as a fraction of total travel distance
  • peak — where along the path the arc reaches maximum height (default 0.5 = symmetric)
  • direction"cw" / "ccw" to fix which side the arc bulges toward; when unset, auto-picks a consistent screen-space direction regardless of travel direction
  • orientToPath — rotates the element to follow the tangent of the arc path. higher number = more intensity

Opinionated choices:

  • Arc only applies to x/y motion — other animating properties (e.g. scale) are unaffected
  • Interrupted layout animations continue arcing to the same side as the interrupted animation

Test plan

  • useAnimate example toggles between positions along an arc
  • Keyframe examples show ghost (straight) vs arc element side-by-side for x, y, diagonal, and diagonal+scale
  • Toggle layoutId element between positions — should travel in a curve, not a straight line
  • Adjust amplitude slider — 0 = straight line, 1 = arc equal to travel distance
  • Adjust peak — arc should shift earlier/later along the path
  • Set direction — arc should lock to cw or ccw regardless of movement direction
  • Interrupt a layout animation mid-arc — new arc should continue bulging to the same side
  • Test horizontal, vertical, and diagonal layout animation cases

Comment thread packages/motion-dom/src/projection/node/create-projection-node.ts
@lochie lochie closed this Oct 5, 2025
@lochie
Copy link
Copy Markdown
Contributor Author

lochie commented Oct 5, 2025

closing PR while i work on it

@lochie lochie reopened this Mar 12, 2026
@lochie
Copy link
Copy Markdown
Contributor Author

lochie commented Mar 12, 2026

back at it 🫡

@lochie lochie changed the title wip feat: arcs in layout transitions feat: arc path for layout and keyframe animations Mar 12, 2026
@lochie lochie marked this pull request as ready for review March 12, 2026 19:11
Copy link
Copy Markdown

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@lochie
Copy link
Copy Markdown
Contributor Author

lochie commented Mar 13, 2026

@mattgperry drag-momentum test is failing here but passes locally. is this a known issue?
edit: seems like it's working now

@lochie
Copy link
Copy Markdown
Contributor Author

lochie commented Mar 18, 2026

@mattgperry I've just been thinking, would this be more suitable as a cubic bezier instead of this amplitude/peak logic?

I originally set this up to make it as easy as possible to enable curves but it does feel a little difficult to customise.

Caveats are we'd lose the ability to have the "smart" checks that change logic based on context. Alternatively we could include both options with the ampltitude/peak logic being advertised as "smart"?

Before CleanShot —03-19 at 01 24 27@2x
After CleanShot —03-19 at 01 27 58@2x

@lochie
Copy link
Copy Markdown
Contributor Author

lochie commented Apr 23, 2026

@mattgperry i know you're probably busy, but just curious if you've had any thoughts on this

@mattgperry
Copy link
Copy Markdown
Collaborator

Hey @lochie! Sorry for the delay. Yeah I have some thoughts. I think it's looking good though.

Maybe nice shorthands?

arc: true / arc: 0.5

I think bezier curve is getting close to offset path which we already basically support for normal animations - though I appreciate they don't work with layout animations.

In terms of bundling I would like it to have minimal impact so I'm going to take a quick go at making it injectable also.

@lochie
Copy link
Copy Markdown
Contributor Author

lochie commented May 6, 2026

@mattgperry all good! shorthand sounds like a good idea.
want me to pause and let you figure out the bundling situation? im not familiar with how it's set up for this library

@mattgperry
Copy link
Copy Markdown
Collaborator

Yeah hold off for now, I've got a branch I'm quite happy with, I'll get back to you with a PR to see if you're happy with it too

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