16

Creating a Sliding Menu in React

Sliding menus are all the rage in UIs today. All the cool kids are building them, and your friends probably just can’t get enough of them. These menus are basically off-screen elements that slide into view when you click or tap on something. That something could be an arrow, a hamburger icon, or something else that indicates a menu will appear.

To see a sliding menu in action, go here: https://www.kirupa.com/react/examples/slidingmenu_css/index.html.

You’ll see a yellow menu with some navigation links smoothly slide in. If you click a navigation link or anywhere in the yellow region inside that menu, the menu slides back (really smoothly again, of course) and the content behind it reappears. Let’s look at how to create all of this using React.

Note: For a Non-React Solution

If you’re looking to create this menu using plain JavaScript without any React wizardry, the tutorial Creating a Smooth Sliding Menu (http://bit.ly/plainSidingMenu) has you covered.

How the Sliding Menu Works

Before we jump into the code, let’s take a few moments to better understand how exactly our sliding menu works. Starting at the very top, we have our page that displays some content:

A figure shows a blue circle at the top-left area of the screen, and a list of menu options are displayed below it.

When you decide to bring up the menu (by clicking/tapping the blue circle in our example), the menu magically slides into view:

A figure shows the menu options appearing as they slide from the left end of the screen.

The way this sliding menu works isn’t as crazy as it seems. The menu is never truly nonexistent; it is simply hidden outside the view. To see what that looks like, check out the following diagram:

A figure shows the menu screen on the left, and the browser screen after the menu slides into place. The menu is indicated to be nonexistent before it slides into the screen, and the width of the menu is shown to be same as the browser width.

Just to the left of the content what we see is our menu, patiently hiding until it is called upon. We do that by shifting the menu as far left as we can until it’s fully out of view. Figuring out how far to shift is easy. Our menu’s size is the same as our browser’s window (a.k.a. the viewport) size because we want the menu to fully cover up whatever is shown. Given that detail, we just shift the menu left by the browser’s width. One way of doing that might be by using some CSS that looks as follows:

We set our menu’s position to fixed. This single change gives our menu a whole lot of magical capabilities. For starters, it ensures that normal layout rules no longer apply to it. We can position our menu anywhere we want using normal x and y values, and the menu won’t shift away from where we have it positioned. If that isn’t awesome enough, our menu won’t even display a scrollbar if we happen to hide it somewhere offscreen.

All this is a good thing because we hide our menu offscreen by setting our menu’s left and top properties to 0 and setting our menu’s transform property to a translate3d method with a horizontal value of -100vw. The negative value ensures that we shift the menu left by the amount equivalent to our browser window’s width. While not directly related to position, the size of our menu plays an important role as well. That’s why, in this CSS snippet, we have the width and height properties set with values of 100vw and 100vh, respectively, to ensure that our menu’s size is the same as our browser window’s size.

What Are These vw and vh Units?

If you’ve never seen the vw and vh units, they stand for viewport width (vw) and viewport height (vh). They’re a bit similar to percentage values. Each unit is 1/100th the width or height of your viewport (what we’ve been simply calling the browser window). For example, a value of 100vw means that its value is the full width of our browser window. Similarly, 100vh refers to a value that is the full height of our browser window.

When the menu is called upon to slide into view, we slide the menu right until its horizontal position is the same as our browser window origin. If we had to look at what the CSS for it might look like, this would be an easy change from what we already have. We simply set our transform property’s translate3d method and set the horizontal position to a value of 0vw.

That might look something like this:

This change ensures that our menu is shifted right from being hidden offscreen (with a horizontal translate value of -100vw) and is now visible. When our menu needs to disappear, we can translate it back:

The biggest thing we haven’t spoken about is the animation that makes the sliding look cool. This is done using a simple CSS transition that animates the transform property:

If you’re not familiar with CSS transitions, it’s a very simple concept to wrap your brain around. I don’t explain it here, so take a few moments and read through the short Introduction to CSS Transitions article (https://www.kirupa.com/html5/introduction_css_transitions.htm) for an overview.

So far, we’ve taken a bird’s-eye view of how our sliding menu works. A few details need to be looked at, but we’ll do that in the next couple sections when we actually build this menu.

Setting Up the Sliding Menu

Now that you have a basic idea about how a sliding menu works, let’s turn all that theoretical knowledge into some sweet JSX and code. The first thing we’re going to do is look at our example in terms of the individual components that will make it up.

At the very top, we have our MenuContainer component:

The figure shows the sliding menu with the blue circle at the top-left and the list of menu options below it. This is indicated to be the MenuContainer component.

This component is responsible for doing nonvisual things like managing state, hosting our Menu and MenuButton components, and displaying some of the initial text. The bird’s-eye view looks a bit like this:

The figure shows the MenuContainer component having two children: the MenuButton and the Menu.

In the next few sections, we’ll start creating these components and getting the example up and running.

Getting Started

Use create-react-app to create a new project called slidingmenu. If you aren’t familiar with how to do that, check out Chapter 13, “Setting Up Your React Dev Environment Easily,” to walk through the details of creating and working with React projects. After you’ve created your project, you want to start from a blank slate. Delete everything in your public and src folders. You’ll re-create the necessary pieces shortly.

Let’s start by creating our HTML document. In your public folder, create a file called index.html. Inside it, add the following contents:

This HTML page is simply the destination where all of our React components will eventually render their output.

Next, you want to create a file called index.js in the src folder that will be responsible for teeing things up in the code. Add the following content into this file:

The render call here is responsible for displaying the output of our MenuContainer component into the container div element we specified in HTML a few moments ago. In our import statements, besides pulling in the react and react-dom libraries, we are referencing index.css and our MenuContainer component. That’s all there is to our index.js file.

Next we’re going to create the index.css file in our src folder and get the page’s basic styling defined. In this file, add the following two style rules:

There isn’t much to say about these style rules, so the last thing we do to get our initial app set up is create our MenuContainer component. Create a file called MenuContainer.js in the src folder and add the following JS and JSX into it:

Be sure to save the changes you made to all of your files, and test your app (using npm start) to ensure that your initial setup of the app works fine. If everything worked out properly, your default browser will launch and you’ll see something that looks as follows:

The text "Can you spot the item that doesn't belong?" is displayed on the screen, with the following list of items displayed as text below it: Lorem, Ipsum, Dolor, Sit, Bumblebees, Aenean, and Consectetur.

There’s no menu to slide or button to press; we’ll add both of those in the next couple sections.

Showing and Hiding the Menu

With the initial setup out of the way, it’s time for the fun part: actually building the menu. Our menu is shown or hidden as follows:

1. When you click a button, the menu slides into view.

2. When you click anywhere on the menu, the menu slides out of view.

This means that we need to account for a few things going on. We need to maintain some state to keep track of whether the menu is hidden or shown. This state needs to be something we update from both the button and the menu because clicking on either will toggle whether the menu is visible. We need our state to live in a common location that both the menu and the button can access. That common location will be inside our MenuContainer component, so let’s add the code relating to our state logic.

In the MenuContainer.js file, add the constructor and toggleMenu methods just above our render method:

The code you’ve just added should look like a walk in the park by now. You’re storing a variable called visible in your state object, and you’re creating a method called toggleMenu that will be responsible for toggling whether visible is true or false.

Next up is dealing with the click events on the button and menu. If the goal is to update our state from inside our MenuContainer component, we need to place our event handler inside MenuContainer as well. Go ahead and add the following highlighted lines:

When the handleMouseDown method is called, we call toggleMenu, which toggles whether the menu appears. At this point, you’re probably wondering where the actual code for dealing with a click event is. What exactly will trigger a call to handleMouseDown? The answer is, nothing so far! We’ve done things in a bit of a reverse order and defined our event handler first. We handle the association between our event handler and our click event in a few moments when dealing with our button and menu components.

Creating the Button

In your src folder, create two files called MenuButton.js and MenuButton.css. Then open MenuButton.js in your code editor. Inside it, add the following lines of code:

Take a moment to see what this code is doing. There isn’t a whole lot going on. We define a button element called roundButton, and we associate the onMouseDown event with a prop we are referencing as handleMouseDown. Before moving on, open MenuButton.css and add the following style rules:

Now it’s is time to actually instantiate our newly created MenuButton component. Go back to the MenuContainer component and add the following highlighted line inside the render method:

For this line to actually do something, be sure to add the appropriate import statement at the top for our MenuButton.js file. That’s an easy one to overlook!

Notice that we are passing in a prop called handleMouseDown, and its value is the handleMouseDown event handler that we defined earlier. This ensures that when you click the button inside the MenuButton component, the handleMouseDown method that lives in the MenuContainer component gets called. All of this is great, but our button isn’t very useful without a menu to help slide into view. We’ll fix that next.

Creating the Menu

It’s time to create our Menu component that will be responsible for all things dealing with the menu. Before we actually create this component, let’s pretend that it already exists and call it from our render method inside our MenuContainer. Add the following highlighted call to our (currently imaginary) Menu component just below where you added the call to MenuButton a few short moments earlier:

Add the import statement for Menu.js as well. Getting back to the Menu component, look at the props you’re passing in. The first prop should look familiar to you. It is handleMouseDown and its value is our handleMouseDown event-handling method. The second prop is called menuVisibility. Its value is the current value of our visible state property. Now let’s go ahead and actually create our Menu component and see, among other things, how these props get used.

In the same src folder we have been partying in for the past few sections, add one file called Menu.js and another file called Menu.css. Inside Menu.js, add the following contents:

Pay attention to the JSX in the return statement. We have a div element called flyoutMenu with some sample content. In our div element, we call our handleMouseDown event-handling method (passed in via a prop) when the onMouseDown event is overheard. Next, we set a class value on this element; the value is the result of evaluating a variable called visibility. As you might recall, class is a reserved name in JavaScript and you can’t use it directly in our JSX; it has to be specified as className.

Getting back to our code, the value of visibility is set a few lines earlier:

The value is either hide or show, depending on whether the menuVisibility prop (whose value is specified by our visible state property) is true or false. While it might not look like it, the code revolving around className plays a really important role in determining whether your menu is actually visible. When we look at our CSS, you’ll see why. Now open Menu.css and add the following style rules into it:

The CSS you see here mostly deals with how our menu itself looks, but the actual showing and hiding of the menu is handled by the #flyoutMenu.hide and #flyoutMenu.show style rules. Which of these style rules becomes active depends entirely on the code we looked at earlier. In our flyoutMenu div element, remember that the class value on the generated HTML (which our CSS maps to) will be either hide or show, depending on what value we set for className. Pretty cool, right?

At this point, we’re fully done with all our coding. Be sure to save all your changes and ensure that the app works just like the example we started with. Don’t nuke this project, though. We’ll be revisiting this and addressing some major shortcomings in a little bit.

Conclusion

This is one of the first examples we’ve looked at in which we’re using React to create a common UI occurrence, a sliding menu. As part of this, you learned more about the interplay between components, such as dealing with events/event handlers, sharing state, and so on. As we look at more examples together, you’ll see that there isn’t a whole lot more to React than what you’ve seen here. All that remains is a clever arrangement and rearrangement of the same concepts in more complex scenarios. This doesn’t mean we’re done, though. There’s more React to be had and more examples to create and fully understand!

Note: If you run into any issues, ask!

If you have any questions or your code isn’t running like you expect, don’t hesitate to ask! Post on the forums at https://forum.kirupa.com and get help from some of the friendliest and most knowledgeable people the Internet has ever brought together!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset