# Handoff from Framer
How to convert interactive Framer prototypes into production.Motion is the library driving Framer's animation and gesture capabilities, so converting prototypes into production-level code is usually straightforward.
In this guide we'll cover the main differences between the libraries.
# Striking a balance
Every API has to strike a balance between simplicity, flexibility, performance, file-size, and more.
That ideal balance is different depending on whether our code is being used in a prototype, or being deployed in a production environment. Whether it's being consumed by a designer, or a developer. This is why Motion presents a different API than Framer Library.
# Frame vs Motion components
The single biggest difference between the two APIs is that in Framer Library the fundamental building block is a Frame
, while Motion uses motion
components.
A Frame
always renders a div
, and it offers a number of top-level convenience style props like x
and shadow
. It also makes big assumptions about the div
's default styles, like position: "absolute"
and width: 100
.
<Frame x={100} />
For a semantic web, there's a motion
component for every valid HTML and SVG element. They offer the same animation and gesture API as a Frame
as well as individual transform shortcuts like x
and scale
, but they're otherwise identical to their underlying element.
<motion.div style={{ x: 100 }} />
# MotionValues
MotionValue
s are bound to a Frame
where you'd statically set a visual value, which for a Frame
is usually the top-level props like x
.
const x = useMotionValue(0)
return <Frame x={x} />
The same is true for motion
components. MotionValue
s are set where you'd usually static set a value. So for HTML components, this is via the style
property.
const x = useMotionValue(0)
<motion.div style={{ x }} />
For SVG, via the top-level prop for attributes, or the style
property for transforms.
const cx = useMotionValue(0)
const scale = useMotionValue(1)
const originX = useMotionValue(0.5)
<motion.circle cx={cx} style={{ scale, originX }} />
# Color support
Framer Library offers the Color
primitive. This allows animation between named colors, and/or different types of color (ie RGBA to HSLA).
<Frame
initial={{ backgroundColor: Color("red") }}
animate={{ backgroundColor: Color("#fff") }}
/>
The code that interpolates between different color spaces is quite large. It's useful in a prototype environment but in production style guides and design systems usually define colors in a single color space.
For this reason Motion only supports animating colors between RGBA/Hex, or HSLA. It also doesn't support the animation of named colors.
<motion.div
initial={{ backgroundColor: "#f00" }}
animate={{ backgroundColor: "#fff" }}
/>
# Scroll
In Framer, scrollable areas are created with the Scroll
component. On the web, the entire viewport is scrollable. So instead Motion offers the useViewportScroll
hook which returns four read-only MotionValue
s that can be used to power scroll-driven animations.
There isn't currently an equivalent for scrollable elements (via overflow: scroll
), but it is possible to set up an equivalent system with useMotionValue
and onScroll
.
const scrollX = useMotionValue(0)
const handleScroll = e => {
scrollX.set(e.nativeEvent.target.scrollLeft)
}
return <div onScroll={handleScroll} />