Creating a Smooth Animated Menu with React and Framer Motion
Introduction
Building an intuitive and engaging user experience often involves adding motion to UI elements, making the interface feel more dynamic. In this post, I’ll guide you through how I built a menu with smooth, staggered animations using React and Framer Motion. By leveraging these technologies, I achieved a polished interaction flow, enhancing the menu’s functionality and visual appeal.
Here’s how I approached the task.
Tools and Libraries
For this project, I used:
- React: To structure and manage the UI components using custom hooks paradigm.
- Framer Motion: A powerful library for animations in React, enabling declarative and complex animations with ease.
- TypeScript: For adding type safety to the components.
Setting up the Component
The main component, AnimatedMenuButtons
is responsible for rendering the menu items and handling their animation states. Here’s a breakdown of the key parts of the code:
1. Component Props
The component takes in three main props:
-
menuItems
: An array of menu items. -
MenuButton
: A custom React component for rendering the menu buttons.
Code snippet:
interface Props {
menuItems: any[];
MenuButton: React.FC<any>;
}
2. Animation Setup
Using Framer Motion’s motion
and stagger
features, I set up a staggered animation to display the menu items sequentially, creating a smooth transition. The staggerMenuItems
function delays the appearance of each list item by 0.24
seconds.
Code snippet:
const staggerMenuItems = stagger(0.24, { startDelay: 0.05 });
This creates a clean, staggered animation where each button slides into view after a short delay and disappear the same way upon click.
Adding Animations with Framer Motion
3. Handling Animations
I used the useAnimate
hook from Framer Motion to control the animation. The animate
function handles the transitions for the menu items. Initially, each menu item (li
) starts with zero opacity and is translated 200px
to the right, which then animates to full opacity and its original position.
animate(
"li",
{ opacity: 1, translateX: 0 },
{
duration: 0.8,
delay: staggerMenuItems,
}
);
4. Click Animation
When a menu item is clicked, the clickHandler
triggers an animation where the item fades out and slides back to the right. This animation runs before triggering the onClick
event provided by the menu item.
const clickHandler = (onClick: () => void) => {
animate(
"li",
{ opacity: 0, translateX: 200 },
{
duration: 0.8,
delay: staggerMenuItems,
onComplete: () => {
// Important note: mind here that this callback will invoke for each of the <li/> items and if this is not intended, use the then chain callback to run only once.
},
}
).then( onCompleteFunc );
};
This approach ensures the button clicks are animated smoothly, providing a more immersive experience for the user.
Rendering the Menu Items
Each menu item is rendered inside a motion.li
component, where the initial animation state is defined. The onClick
event is passed down to trigger the clickHandler
, which runs the animation before executing the item's click logic.
Code snippet:
<motion.li
key={index}
initial={{
opacity: 0,
translateX: 200,
}}
onClick={() => clickHandler(item.onClick)}
>
<MenuButton {...item} />
</motion.li>
Conclusion
Using Framer Motion in React made it straightforward to build an interactive menu with smooth animations. The ability to easily control animation sequences, such as staggered entrances and exits, adds a layer of sophistication to the UI.
If you’re looking to enhance your next project with modern animations, I highly recommend giving Framer Motion a try. It’s incredibly versatile, and with just a few lines of code, you can transform a static interface into something dynamic and engaging.
The full code can be found here:
https://codesandbox.io/p/sandbox/animated-menu-65zz88
Stay tuned for more animation tips!
Let me know in the comments how it worked for you!
Top comments (0)