Create smooth sidebars with react-pro-sidebar and MUI
Tags: react, webdev
Published: 2023-01-04 18:05:39

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](https://blog.logrocket.com/create-responsive-navbar-react-css/), 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?](#what-are-we-building)
*   [What is react-pro-sidebar?](#what-is-react-pro-sidebar)
*   [What are MUI icons?](#what-are-mui-icons)
*   [Installing dependencies](#installing-dependencies)
*   [Wrapping react-pro-sidebar](#wrapping-react-pro-sidebar)
*   [Adding global styles](#adding-global-styles)
*   [Building the application](#building-the-application)
    *   [Reversing the sidebar direction](#reversing-the-sidebar-direction)
    *   [Toggling the sidebar and changing the background color](#toggling-the-sidebar-and-changing-the-background-color)
    *   [Breakpoints and transition duration](#breakpoints-and-transition-duration)

## 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](https://www.npmjs.com/package/react-pro-sidebar) while following this tutorial.

## What are MUI icons?

[Material UI](https://blog.logrocket.com/definitive-guide-react-material/) 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:

```javascript
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>
);
```

## 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:

```javascript
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;
}
```

## 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:

```javascript
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";
```

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.

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

export default App;
```

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:

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

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](https://blog.logrocket.com/wp-content/uploads/2022/12/sidebar-collapsed-with-icon-and-removed-text.png) 

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

```javascript
<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>
```

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

```javascript
<main>
        <h1 style={{ color: "white", marginLeft: "5rem" }}>
          React-Pro-Sidebar
        </h1>
      </main>
```

This is what our application should look like now: ![Sidebar With Options And Icons Not Collapsed](https://blog.logrocket.com/wp-content/uploads/2022/12/sidebar-with-options-and-icons-not-collapsed.png) 

And this is what it looks like if we press the `Admin` text so that the sidebar collapses: ![Sidebar With Icons Collapsed](https://blog.logrocket.com/wp-content/uploads/2022/12/sidebar-with-icons-collapsed.png) This is the final version of our component so far:

```javascript
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;
```

### 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:

```javascript
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>
```

Now, the app should look like this: ![Sidebar With Orientation Variant Right Side](https://blog.logrocket.com/wp-content/uploads/2022/12/sidebar-with-orientation-variant-right-side.png)

### 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:

```javascript
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" }}
      >
...
```

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

```javascript
<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>
```

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](https://blog.logrocket.com/wp-content/uploads/2022/12/sidebar-with-color-not-toggled.png) 

![Sidebar Background Color Toggled](https://blog.logrocket.com/wp-content/uploads/2022/12/sidebar-background-color-toggled.png) 

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:

```javascript
<Sidebar
        breakPoint="sm"
        transitionDuration={800}
...
```

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

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

![Sidebar Small Screen Breakpoint](https://blog.logrocket.com/wp-content/uploads/2022/12/sidebar-small-screen-breakpoint.png) 

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](https://blog.logrocket.com/wp-content/uploads/2022/12/react-pro-sidebar-all-variations.gif) 

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](https://github.com/muratcan-yuksel/react-pro-sidebar). Let me know what your experiences are using react-pro-sidebar in the comments.