Edit Page

#Handoff from Framer X

How to convert interactive Framer X prototypes into production.

Motion is the library driving Framer X'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

MotionValues 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. MotionValues 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 X, 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 MotionValues 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} />