By default, when Motion animates x and y between two values, the element travels in a straight line. arc() can bend that line.
import { arc, motion } from "motion/react"
<motion.div
animate={{ x: 200, y: 100 }}
transition={{ duration: 1, path: arc() }}
/>
arc() is passed to transition.path. It works with motion components, animate, and useAnimate.
Usage
Import arc from "motion" or "motion/react".
import { arc } from "motion"
When passed to transition.path, it will automatically curve the line between two x and y points.
const path = arc({ strength: 1 })
animate(".box", { x: 200, y: 100 }, { duration: 1, path })
Keyframe animations
transition.path works anywhere a transition is accepted. The path interpolates between the first and last x/y value, including across keyframe arrays.
<motion.div
animate={{ x: [0, 200], y: [0, 100] }}
transition={{ duration: 1, path: arc({ strength: 1 }) }}
/>
// useAnimate
const [scope, animate] = useAnimate()
animate(
scope.current,
{ x: 200, y: 100 },
{ duration: 1, path: arc({ strength: 1 }) }
)
Layout animations
Pass arc() to transition.layout.path to curve the motion of a layout animation. This is where arc() does work straight-line interpolation can't: every element moving from A to B will follow a curve, even when A and B are defined by surrounding layout rather than fixed keyframes.
<motion.div
layout
transition={{
layout: { duration: 0.6, path: arc({ strength: 0.6 }) },
}}
/>
It also works with layoutId for shared element transitions:
<motion.div
layoutId="bubble"
transition={{ layout: { path: arc() } }