Animated Filtering List with React & Framer Motion
How I built the animated topic filtering feature on the homepage.
Filtering Posts with React Context
The basic structure is simple. I have two separate components on the homepage.
One component is for listing topics covered by the blog: <PostTagsList />
The other component is a list of the the blog posts themselves: <BlogItem />
Since the two are on the same page and only interact here, I'd normally just leverage parent state so the two could share data.
However, I wanted some practice with React Context which allows you to share data across components easily.
If you select one of the topics from the PostTagList
, that topic string is set to context, then consumed by the array of posts.
I use the filter method and use that topic to filter the posts.
Functionally, this is perfect. It works as expected
Animating the filtered list with Framer Motion
With Framer Motion animating these changes was pretty straightforward.
First, I NPM installed framer-motion and imported it on the <BlogItem>
component.
import { motion, AnimatePresence } from "framer-motion"
The outside wrapper is <AnimatePresence>{all your code}</AnimatePresence>
.
Wrapping the component in this allows it to animate even though the item itself is being removed. You run into this timing issue a lot. If the item is removed in milliseconds, how can it be animated out gracefully.
Before you would need animate the item out visually, then have it actually removed. Framer Motion is handling this for us.
Properties for the items
Each blog post on the homepage lives within an unorder list. <ul>
.
Each list item needs motion added to it, to tell motion we're working with this element.
Then you can add motion specific props. Initial, is the inital style you want at the beginning of the animation. Once it animates, the animate prop is what it will animate to. And exit, is what it will animate to on it's way out.
The layout prop is added to give each item contexual awareness to other items on the list.
It's a feature best experienced by simply trying it. It's not required. Try sorting the list without it..then add it in and look for the change in behavior.
Instead of simply fading content in and out, items that were at the bottom of the list, that are suddenly filtered to the top of the list will slide there.
Then, if you remove those filters, to get the big list back, you'll see that item slide back to it's previous place vs. disappearing then reappearing.
<motion.li
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
layout
>
{code inside the li}
</motion.li>
That is actually it. We imported Framer Motion, then told it what we wanted animated, and the styles to that animation (fade in/fade out), and that's it.
I'll be adding more of these examples soon. Cheers.