DEV Community

Cover image for Create smooth sidebars with react-pro-sidebar and MUI
Matt Angelosanto for LogRocket

Posted on • Originally published at blog.logrocket.com

Create smooth sidebars with react-pro-sidebar and MUI

Navigation is an extremely important aspect of web development to consider when we want to provide a compelling user experience — users should be able to know where they are and quickly switch between pages without getting lost.

In order to assure smooth browsing, we tend to gravitate towards adding a top or side navigation bar, but implementing this functionality can be very time-consuming, and so a quicker alternative can be useful in these use cases.

Luckily, we have ready-made solutions for many of our problems, including this one!

In this tutorial, I’ll show you how to use react-pro-sidebar to add an animated sidebar to your React application. We will also make use of Material UI icons for a more professional aesthetic for the purposes of a positive user experience.

Jump ahead:

What are we building?

We will be building a simple application that consists of a sidebar and a main page.

The main page will only have a title on it, while the sidebar will have multiple elements with adjacent icons to demonstrate its functionality.

When the user clicks the sidebar, it will collapse and only expand if clicked again.

What is react-pro-sidebar?

As noted in their docs, “react-pro-sidebar provides a set of components for creating high-level and customizable side navigation.” In short, it makes creating sidebars in React a breeze — good news for us!

While there are other competitors around, react-pro-sidebar is extremely popular within the community and is the safest bet for this particular use case in my opinion. If you’d like to learn more about the package in general, you can check out the official docs while following this tutorial.

What are MUI icons?

Material UI icons are the set of icons we’ll be using today. You don’t need to do your styling with MUI or know much about it at all; the only thing you need to do for this tutorial is to install the relevant packages, which we’ll get to in a moment.

In my experience, MUI icons enable rapid development because instead of looking for different icons in various places, everything we need can be found here. In general, I find MUI very useful in my projects and highly recommend its use.

Installing dependencies

First off, let’s create our React application with the React CLI by entering the npx create-react-app sidebar-project command in our terminal.

Of course, you can choose any name you want for the project, I‘m using sidebar-project as the name for this tutorial.

Now, we need to install Material UI, its icons, and react-pro-sidebar for this tutorial.

Let’s go into the sidebar-project application we’ve just created and enter the following commands on the terminal:

npm install @mui/icons-material @mui/material @emotion/styled @emotion/react react-pro-sidebar

Now, we’re good to go!

Wrapping react-pro-sidebar

In order to use the react-pro-sidebar, we need to wrap our components within a ProSidebarProvider component that we’ll import from the package.

Take a look at the index.js where I’ve wrapped my application:

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import { ProSidebarProvider } from "react-pro-sidebar";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <ProSidebarProvider>
      <App />
    </ProSidebarProvider>
  </React.StrictMode>
);
Enter fullscreen mode Exit fullscreen mode

Adding global styles

Before we start building the logic, I want to add some global CSS, so I’ll go to the index.css file and add two lines of code there.

In the body tag, I’ll add a height of 100vh and a black background to the existing lines.

This is how it should look, once complete:

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
    "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* additions here*/
  height: 100vh;
  background: black;
}
code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
    monospace;
}
Enter fullscreen mode Exit fullscreen mode

Building the application

Now that our application is wrapped and we have our global styling, we can start building our logic.

Let’s go to our App.js file and start by importing the following from the react-pro-sidebar package:

import { Sidebar, Menu, MenuItem, useProSidebar } from "react-pro-sidebar";

While the first three imports are related to the UI, useProSidebar is a hook that lets us access and manage sidebar state. In the react-pro-sidebar documentation, it’s explained as such:

collapseSidebar: (collapsed?: boolean) => void: A function that enables you to update the sidebar's collapsed state.

Now, we need to import the icons we’ll use for the sidebar. We don’t have to use these icons, but I like to use them because they help make the sidebar look a little bit more professional, as you might expect in a real-world use case.

So, just under our first import, let’s paste these lines:

import HomeOutlinedIcon from "@mui/icons-material/HomeOutlined";
import PeopleOutlinedIcon from "@mui/icons-material/PeopleOutlined";
import ContactsOutlinedIcon from "@mui/icons-material/ContactsOutlined";
import ReceiptOutlinedIcon from "@mui/icons-material/ReceiptOutlined";
import CalendarTodayOutlinedIcon from "@mui/icons-material/CalendarTodayOutlined";
import HelpOutlineOutlinedIcon from "@mui/icons-material/HelpOutlineOutlined";
import MenuOutlinedIcon from "@mui/icons-material/MenuOutlined";
Enter fullscreen mode Exit fullscreen mode

Now that we’re done with our imports, we can start using them.

We first have an empty functional component, as per usual. Then, we can start adding some styles to the div, using the ID of app, so that the component will take the full window height and use flexbox — this is because we want to have the sidebar and a basic title next to it.

We can also add a constant of collapseSidebar that’s using the useProSidebar hook coming from the react-pro-sidebar package. This hook, as mentioned before, will help us implement the collapse functionality.

function App() {
const { collapseSidebar } = useProSidebar();
  return (
    <div id="app" style={({ height: "100vh" }, { display: "flex" })}>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Inside this div, I’ll add a Sidebar component that wraps a Menu component and a handful of MenuItem components that we’ve imported from react-pro-sidebar.

We will also input a height of 100vh to the Sidebar, so that it takes up the full height of the screen.

Next, we add the first MenuItem inside the Menu wrapper. Then, we add menuOutlinedIcon from Material UI, and then add a style that aligns the text we’ll put inside of it to the center, before finally adding an onClick event that fires the collapseSidebar hook defined above.

We will also additionally add an h2 element with the text Admin in it, hence the reason for the alignment style:

<Sidebar style={{ height: "100vh" }}>
        <Menu>
          <MenuItem
            icon={<MenuOutlinedIcon />}
            onClick={() => {
              collapseSidebar();
            }}
            style={{ textAlign: "center" }}
          >
            {" "}
            <h2>Admin</h2>
          </MenuItem>
        </Menu>
      </Sidebar>
Enter fullscreen mode Exit fullscreen mode

Easy-peasy! Now, if we click the Admin text, the sidebar should collapse; it’ll even take care of removing the text and leaving only the icon for us. How convenient is this? Sidebar Collapsed With Icon And Removed Text

Now, let’s add the remaining menu items. Still inside the Menu wrapper, under the last line we’ve written, enter the following:

<MenuItem icon={<HomeOutlinedIcon />}>Home</MenuItem>
          <MenuItem icon={<PeopleOutlinedIcon />}>Team</MenuItem>
          <MenuItem icon={<ContactsOutlinedIcon />}>Contacts</MenuItem>
          <MenuItem icon={<ReceiptOutlinedIcon />}>Profile</MenuItem>
          <MenuItem icon={<HelpOutlineOutlinedIcon />}>FAQ</MenuItem>
          <MenuItem icon={<CalendarTodayOutlinedIcon />}>Calendar</MenuItem>
Enter fullscreen mode Exit fullscreen mode

Then, close the Menu tag and add a title; the reason for our flex:

<main>
        <h1 style={{ color: "white", marginLeft: "5rem" }}>
          React-Pro-Sidebar
        </h1>
      </main>
Enter fullscreen mode Exit fullscreen mode

This is what our application should look like now: Sidebar With Options And Icons Not Collapsed

And this is what it looks like if we press the Admin text so that the sidebar collapses: Sidebar With Icons Collapsed This is the final version of our component so far:

import { Sidebar, Menu, MenuItem, useProSidebar } from "react-pro-sidebar";
import HomeOutlinedIcon from "@mui/icons-material/HomeOutlined";
import PeopleOutlinedIcon from "@mui/icons-material/PeopleOutlined";
import ContactsOutlinedIcon from "@mui/icons-material/ContactsOutlined";
import ReceiptOutlinedIcon from "@mui/icons-material/ReceiptOutlined";
import CalendarTodayOutlinedIcon from "@mui/icons-material/CalendarTodayOutlined";
import HelpOutlineOutlinedIcon from "@mui/icons-material/HelpOutlineOutlined";
import MenuOutlinedIcon from "@mui/icons-material/MenuOutlined";

function App() {
  const { collapseSidebar } = useProSidebar();

  return (
    <div id="app" style={({ height: "100vh" }, { display: "flex" })}>
      <Sidebar style={{ height: "100vh" }}>
        <Menu>
          <MenuItem
            icon={<MenuOutlinedIcon />}
            onClick={() => {
              collapseSidebar();
            }}
            style={{ textAlign: "center" }}
          >
            {" "}
            <h2>Admin</h2>
          </MenuItem>

          <MenuItem icon={<HomeOutlinedIcon />}>Home</MenuItem>
          <MenuItem icon={<PeopleOutlinedIcon />}>Team</MenuItem>
          <MenuItem icon={<ContactsOutlinedIcon />}>Contacts</MenuItem>
          <MenuItem icon={<ReceiptOutlinedIcon />}>Profile</MenuItem>
          <MenuItem icon={<HelpOutlineOutlinedIcon />}>FAQ</MenuItem>
          <MenuItem icon={<CalendarTodayOutlinedIcon />}>Calendar</MenuItem>
        </Menu>
      </Sidebar>
      <main>
        <h1 style={{ color: "white", marginLeft: "5rem" }}>
          React-Pro-Sidebar
        </h1>
      </main>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Reversing the sidebar direction

Now, let's say we want our sidebar to be on the right side of the page.

We can easily do that using the rtl (right to left) prop from react-pro-sidebar. To do this, we will make some small changes to the above code.

First, let’s import the rtl prop in the useProSidebar hook, along with the collapseSidebar prop: const { collapseSidebar, rtl } = useProSidebar();.

Then, let's reverse the flexDirection of the page because, at present, it displays the sidebar first and then the main body.

However, since we will soon be reversing the sidebar, it will look strange. So, we'll reverse the page and then set the rtl prop to true, which is false by default. Check out the following snippet:

function App() {
  const { collapseSidebar, rtl } = useProSidebar();
  return (
    <div
      id="app"
      style={
//add flexDirection: "row-reverse" here
        ({ height: "100vh" }, { display: "flex", flexDirection: "row-reverse" })
      }
    >
//add rtl={true}, which was false by default.
      <Sidebar rtl={true} style={{ height: "100vh" }}>
        <Menu>
Enter fullscreen mode Exit fullscreen mode

Now, the app should look like this: Sidebar With Orientation Variant Right Side

Toggling the sidebar and changing the background color

Now, let's add some more functionality to our app.

We want to change the background color of the sidebar and also have the ability to collapse it by toggling while keeping track of its toggle state.

To begin, we’ll change the app to its original state with the sidebar on the left. Then, change the background color by adding the following to our Sidebar element: backgroundColor="rgb(0, 249, 249, 0.7)".

Next, add a toggle function that will log true or false to the console, depending on whether the sidebar is toggled or not. Remove the collapseSidebar function from the menu item and add the toggle function to an onClick event on the title.

Finally, we’ll add some text on the screen that specifies the toggle state to demonstrate what’s happening.

Let's take a look at it in action. This is the toggle function I wrote:

function App() {
  const { collapseSidebar, toggleSidebar, collapsed, toggled, broken, rtl } =
    useProSidebar();
  const toggle = () => {
    toggleSidebar();
    if (toggled) {
      console.log(true);
      collapseSidebar();
    } else {
      console.log(false);
      collapseSidebar();
    }
  };
 return (
    <div
      id="app"
      style={({ height: "100vh" }, { display: "flex", flexDirection: "row" })}
    >
      <Sidebar
//change background color
        backgroundColor="rgb(0, 249, 249, 0.7)"
        rtl={false}
        style={{ height: "100vh" }}
      >
...
Enter fullscreen mode Exit fullscreen mode

And in the main statement, we can add the following:

<main>
        <h1
          onClick={() => {
            toggle();
          }}
          style={{ color: "white", marginLeft: "5rem" }}
        >
          React-Pro-Sidebar
        </h1>
        {toggled ? (
          <h1 style={{ color: "white", marginLeft: "5rem" }}>Toggled</h1>
        ) : (
          <h1 style={{ color: "white", marginLeft: "5rem" }}>Not Toggled</h1>
        )}
      </main>
Enter fullscreen mode Exit fullscreen mode

Now, whenever we click on the React-Pro-Sidebar title on the screen, the title under it will change accordingly. Check out the toggled and untoggled variations in the images below. Sidebar With Color Not Toggled

Sidebar Background Color Toggled

The sidebar’s background color has changed, and I can keep track of the state of the sidebar with the toggle functionality.

Breakpoints and transition duration

If we wanted, we could add even more functionality to the app, such as changing the transition duration of the sidebar or adding breakpoints to exercise different behaviors.

For example, the default transition duration of the sidebar is 300ms, but I want to make it a bit slower, so we can set it to 800ms. I also want to add some text saying "Small screen" when the screen is smaller; to do this, we will have to add two more props to the sidebar, like this:

<Sidebar
        breakPoint="sm"
        transitionDuration={800}
...
Enter fullscreen mode Exit fullscreen mode

Now, to control the breakpoints, we’ll use the broken method:

...    
        {broken && (
          <h1 style={{ color: "white", marginLeft: "5rem" }}>Small screen</h1>
        )}
      </main>
Enter fullscreen mode Exit fullscreen mode

Sidebar Small Screen Breakpoint

The above text will only show up on smaller screens.

It is also worth noting that using breakpoints with react-pro-sidebar has the following behavior: when on a small screen, at each "not toggled" state, the sidebar will disappear, and when toggled again for the "toggled" state, the sidebar will show up as wide, and then narrow on the next cycle.

Let me show you how it works.

We’ll make the screen even smaller and bring back the "Toggled"/"Not Toggled" messages from the previous example for ease of understanding: React Pro Sidebar All Variations

If we collapse the sidebar from the previous example, you can see it will completely disappear. If we click once more, it will show up as wide, but with less opacity so that the text underneath can be read easily.

I’m pretty confident from my experience that this behavior captures all possible user inputs in using sidebars on small screens.

Conclusion

In this tutorial, we’ve seen how to add a responsive, dynamic sidebar using the react-pro-sidebar package. We also showed how combining it with Material UI icons allows us to quickly create a smooth sidebar while maintaining a professional look and feel that should be expected from a real-world project.

If you would like to take a look at the finished version of this build, feel free to check out the repo. Let me know what your experiences are using react-pro-sidebar in the comments.

Top comments (0)