Skip to content

feat: arc path for layout and keyframe animations#3386

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

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

Conversation

@lochie
Copy link
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

@lochie lochie closed this Oct 5, 2025
@lochie
Copy link
Contributor Author

lochie commented Oct 5, 2025

closing PR while i work on it

@lochie lochie reopened this Mar 12, 2026
@lochie
Copy link
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

@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
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
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

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.

1 participant