I mentioned recently that I had tried Framer Motion, a React library for animations.

I used it in Operator Lookup ( https://joshwcomeau.com/operator-lookup/), a project I launched earlier this week. 🎉

In this thread, I'll share some of the tricks I learned to create animations like this 👇🏻
Probably the most obvious animation on the whole project is the slide-up effect, shown in the above tweet.

There are two parts to it:
• The header fades out
• The text input slides up, to occupy this space.

Here's the code for it!

(view in text: https://pastebin.com/fTaeDwJK )
The trick is, I'm unmounting the header when a search result is matched. I'm not just hiding it with CSS.

The `AnimatePresence` helper ( https://www.framer.com/api/motion/animate-presence/) allows you to specify "exit" animations. Here I'm fading it out before it gets removed from the DOM.
After the element finished fading out, there's a hole in the DOM. The search input will naturally move up to fill that space, but normally, it would happen instantly.

That's where <AnimateSharedLayout> ( https://www.framer.com/api/motion/animate-shared-layout/) comes in, which is honestly pure magic ✨
It uses a FLIP animation to figure out where this fella needs to move to, and then applies a transition to make it so. To "activate" it, all you need to do is set `layout={true}` to any descendant of `AnimateSharedLayout`.

This would be *such* a hard problem otherwise.
In my snippet, you may have noticed:

layout={!prefersReducedMotion}

The idea here is that this layout animation doesn't happen for folks who have expressed a preference against motion.

I've written about this: https://joshwcomeau.com/tutorials/accessibility/
I'm honestly kinda floored by how little code was required to do this animation. Animating layout shifts is a Hard Problem. I solved for it in React Flip Move ( https://github.com/joshwcomeau/react-flip-move), an animation library I created years ago.

It nearly destroyed my brain 😂
One other neat animation in this project is the staggered fade on these suggestions.

This works thanks to the `staggerChildren` prop, https://www.framer.com/api/motion/types/#orchestration.staggerchildren
View code in text: https://pastebin.com/C9FprFus 

TBH, I haven't gone deep enough to 100% understand this stuff 😅 so I may be slightly off in my explanation.

Each list item has an object matching a "variant", either hidden or visible. These are custom names I came up with.
The parent `ul` controls animating from the default `hidden` variant to the `visible` one, and it also includes "transition" information. The critical bit is this:

transition: {
when: 'beforeChildren',
staggerChildren: 0.02,
}
Every child's transition is 20ms after the previous one, which creates the nice domino effect. It also, counter-intuitively, seems to be a bit of a perf win! Because the animation itself is so quick, a smaller number of total transitions occur at any given moment.
Similarly, I use `prefersReducedMotion` to disable this animation when appropriate. I don't disable _all_ animations—there are still some subtle fades—but nothing that conveys a sense of movement, since that is what triggers certain vestibular disorders.
I've only scratched the surface with this library, but it's really neat. I'm excited to keep exploring!

Big thanks to @mattgperry and team, this library is a treasure trove 💯
You can follow @JoshWComeau.
Tip: mention @twtextapp on a Twitter thread with the keyword “unroll” to get a link to it.

Latest Threads Unrolled:

By continuing to use the site, you are consenting to the use of cookies as explained in our Cookie Policy to improve your experience.