Micro-interactions with react-spring: Part 2

In the last article, we examined the basics of micro-interactions: what they are, why they’re important, and how to build one. In this tutorial, we’ll build something I have struggled with for many years: the animated navigation.

Article hero image

In the last article, we examined the basics of micro-interactions: what they are, why they’re important, and how to build one. In this tutorial, we’ll build something I have struggled with for many years: the animated navigation.

Animating navigation is something you’ll probably encounter if you’re a web developer, as our applications and websites need to be responsive, but it can be tricky.You can animate a navigation bar with CSS transitions; however, it’s a bit tedious to find the right bezier curve for the job.

What we’ll build

We’ll use react-spring’s useSpring hook to illustrate how you can build a full page navigation menu and a sidebar which slides in from the right.

Embed Code Sandbox:

Defining the micro-interaction

In the previous blog, we looked at the pieces of a micro-interaction. Let’s define the interaction trigger, state definition, and animation definition for our navigation menu.

Interaction trigger

The visibility of our menu will be triggered by clicking a hamburger menu and dismissed by clicking the X button inside of the menu.

State definition

Our menu will be in one of two states:

  • visible
  • hidden

Animation definition

We will build two menu animations:

  • Right menu, which will slide in from the right and fade in when visible and slide out towards the right and fade out when not visible.
  • Full page menu,which will slide in from the top and fade in when visible and slide out towards the top and fade out when not visible.

Let’s build a menu

First, create a new React Code Sandbox and add react-spring as a dependency.

Next, create two new files: Menu.js and menu.css in the src directory, and add the following code to menu.css. This tutorial won’t cover how to style our menu items, so we’ve provided the code for you.

Menu.css code:

Then add the following CSS to styles.css:

Inside Menu.js, import the following dependencies:

We will create two menus:

  • One that slides in from the right side
  • One that is a full-page overlay

Right Menu

Let's create the right menu. Our menu will have four links:

  • Home
  • About
  • Work
  • Contact

Add the following to Menu.js:

Now, let's import our Menu component into the app and see it render.

In index.js, import the Menu component and replace the h1 and h2 elements from the Code Sandbox default starter with <Menu />.

Index.js code:

Now that our menu is rendering, let's add some state to determine whether or not our menu should be visible.

Inside of index.js, add { useState } to the React import.

Index.js code:

Next, let's declare our state above the return statement. Since our menu will not be visible by default, we'll initialize the state to false.

Now let's define our animation. We want the sidebar to fade in and slide in from the right when visible and fade out and slide out to the left when not visible.

To create this animation, we'll use react-spring's useSpring hook.

Import useSpring from react-spring and underneath the useState hook, declare a new const named rightSidebarAnimation and set it equal to the result of calling useSpring:

Now we'll pass an object to react-spring's useSpring hook which defines the CSS properties we want to animate. In our case, we want to animate opacity and the menu's X-position.

We can use a ternary operator to decide when the opacity should be fully opaque (when visible) or transparent (when not visible) and when the X-position should be 0 (when visible) or 100% (when not visible).

Index.js code:

We also need to trigger the change in visibility. We'll do this by adding a button.

Place a button element above the <MenuRight /> component. When clicked, the button will toggle the state of rightMenuVisible.

We can also use a ternary expression to change the label of the button to "Close" when the menu is open and "Side menu" when the menu is closed.

Index.js code:

Finally, we have to pass rightMenuAnimation to the MenuRight component in order to get it to animate. We'll pass this as the style attribute:

Here is our completed index.js file:

This is what your app should look like:

We have to do a couple more things to get our animation to work:

1. Pass the style attribute to our MenuRight component and add it as an attribute to the HTML element we want to animate.

2. Tell react-spring which element we want to animate.

Back in Menu.js, pass style as an argument to our component and add it as an attribute to our wrapping div.

To complete the second task and see our animation, we have to use a special HTML element to get our modal to animate.

Any element we want to be animated must be prefaced by animated., for example <animated.div>. So let's import { animated } from react-spring and change our <div> elements into animated divs.

Menu.js code:

Your UI should now have a Side Menu button in the top right corner which will transition the menu on click.

And that's it! Your menu should now be transitioning on click.

You can grab the full code here.

Full-page menu

Now let's build our full-page menu. This part of the tutorial will build off of the last section, so if you haven't taken it, you should grab the code at the end of the previous section.

The markup for our full-page menu will be identical to that of the right menu, with the exception of the class name on the outer div being menu--full instead of menu--right.

Add the following React component to your `Menu.js` file:

In index.js, add our MenuFull component to the import:

Let's add another state to show and hide the full menu component.

Underneath the right menu state definition add the following code, which will initialize the visibility state of our full menu to false:

Now let's define our animation. We want our full page menu to start from an opacity of 0 and fade in to an opacity of 1. The menu will also start off the top of the screen (-100%) and transition from the top to take up the entirety of the viewport.

Underneath the rightMenuAnimation add the following:

Let's add a button to toggle the visibility of the full menu. Add this above the side menu button. We'll use the same concept of changing the button text to "Close" when the menu is visible and "Full Menu" when the menu is hidden.

Lastly let's add our component, passing it our transition as the style attribute with our newly declared fullMenuTransition. You can declare it before or after the side menu.

Here is the completed index.js:

And that’s it! Here is our completed full page menu!

You can grab the full code here.


Animating a menu doesn’t have to be complicated! In the next tutorial we’ll build a modal which is mounted and unmounted from the DOM as well as an image gallery!

Login with your stackoverflow.com account to take part in the discussion.