Skip to content
Related Articles

Related Articles

How to create a Responsive Sidebar with dropdown menu in ReactJS?
  • Difficulty Level : Medium
  • Last Updated : 10 Feb, 2021

A sidebar is an important element of a website’s design since it allows users to quickly visit any section within a site.

A glimpse of the project: 

Prerequisite:

  1. npm
  2. create-react-app
  3. react-router-dom
  4. useState React hooks

Basic Setup: You will start a new project using create-react-app so open your terminal and type:



npx create-react-app react-sidebar-dropdown

Now go to your react-sidebar-dropdown folder by typing the given command in the terminal:

cd react-sidebar-dropdown

Required module: Install the dependencies required in this project by typing the given command in the terminal.

npm install react-router-dom
npm install --save styled-components
npm install --save react-icons

Now create the components folder in src then go to the components folder and create three files Sidebar.js, SidebarData.js, and SubMenu.js

Create one more folder in src by the name pages and in pages create files by the name AboutUs.js, ContactUs.js, Events.js, Services.js, Support.js.

Project Structure: The file structure in the project will look like this.

Filename- Sidebar.js: Open & Close Sidebar View, that’s where the role of useState() hook comes into play.

We create a state with the first element sidebar as an initial state having a value of the false and the second element as function setSidebar() for updating the state. Then a function is created by the name showSidebar() which sets the value of the sidebar opposite to its present value whenever it is called. 



This function is used with the menu bars icon and cross icon with the help of onClick() function. When we click on the bars icon to see the sidenav links it sets the value of the state to true, displays the sidebar and a cross icon appears in place of the bars’ icon. When we want to close the sidebar we simply click on the cross icon and it gets replaced with a bar icon after closing the sidebar because now the value of the state is set to false.

Javascript




import React, { useState } from "react";
import styled from "styled-components";
import { Link } from "react-router-dom";
import * as FaIcons from "react-icons/fa";
import * as AiIcons from "react-icons/ai";
import { SidebarData } from "./SidebarData";
import SubMenu from "./SubMenu";
import { IconContext } from "react-icons/lib";
  
const Nav = styled.div`
  background: #15171c;
  height: 80px;
  display: flex;
  justify-content: flex-start;
  align-items: center;
`;
  
const NavIcon = styled(Link)`
  margin-left: 2rem;
  font-size: 2rem;
  height: 80px;
  display: flex;
  justify-content: flex-start;
  align-items: center;
`;
  
const SidebarNav = styled.nav`
  background: #15171c;
  width: 250px;
  height: 100vh;
  display: flex;
  justify-content: center;
  position: fixed;
  top: 0;
  left: ${({ sidebar }) => (sidebar ? "0" : "-100%")};
  transition: 350ms;
  z-index: 10;
`;
  
const SidebarWrap = styled.div`
  width: 100%;
`;
  
const Sidebar = () => {
  const [sidebar, setSidebar] = useState(false);
  
  const showSidebar = () => setSidebar(!sidebar);
  
  return (
    <>
      <IconContext.Provider value={{ color: "#fff" }}>
        <Nav>
          <NavIcon to="#">
            <FaIcons.FaBars onClick={showSidebar} />
          </NavIcon>
          <h1
            style={{ textAlign: "center"
                     marginLeft: "200px"
                     color: "green" }}
          >
            GeeksforGeeks
          </h1>
        </Nav>
        <SidebarNav sidebar={sidebar}>
          <SidebarWrap>
            <NavIcon to="#">
              <AiIcons.AiOutlineClose onClick={showSidebar} />
            </NavIcon>
            {SidebarData.map((item, index) => {
              return <SubMenu item={item} key={index} />;
            })}
          </SidebarWrap>
        </SidebarNav>
      </IconContext.Provider>
    </>
  );
};
  
export default Sidebar;

Filename- SidebarData.js:

Javascript




import React from "react";
import * as FaIcons from "react-icons/fa";
import * as AiIcons from "react-icons/ai";
import * as IoIcons from "react-icons/io";
import * as RiIcons from "react-icons/ri";
  
export const SidebarData = [
  {
    title: "About Us",
    path: "/about-us",
    icon: <AiIcons.AiFillHome />,
    iconClosed: <RiIcons.RiArrowDownSFill />,
    iconOpened: <RiIcons.RiArrowUpSFill />,
  
    subNav: [
      {
        title: "Our Aim",
        path: "/about-us/aim",
        icon: <IoIcons.IoIosPaper />,
      },
      {
        title: "Our Vision",
        path: "/about-us/vision",
        icon: <IoIcons.IoIosPaper />,
      },
    ],
  },
  {
    title: "Services",
    path: "/services",
    icon: <IoIcons.IoIosPaper />,
    iconClosed: <RiIcons.RiArrowDownSFill />,
    iconOpened: <RiIcons.RiArrowUpSFill />,
  
    subNav: [
      {
        title: "Service 1",
        path: "/services/services1",
        icon: <IoIcons.IoIosPaper />,
        cName: "sub-nav",
      },
      {
        title: "Service 2",
        path: "/services/services2",
        icon: <IoIcons.IoIosPaper />,
        cName: "sub-nav",
      },
      {
        title: "Service 3",
        path: "/services/services3",
        icon: <IoIcons.IoIosPaper />,
      },
    ],
  },
  {
    title: "Contact",
    path: "/contact",
    icon: <FaIcons.FaPhone />,
  },
  {
    title: "Events",
    path: "/events",
    icon: <FaIcons.FaEnvelopeOpenText />,
  
    iconClosed: <RiIcons.RiArrowDownSFill />,
    iconOpened: <RiIcons.RiArrowUpSFill />,
  
    subNav: [
      {
        title: "Event 1",
        path: "/events/events1",
        icon: <IoIcons.IoIosPaper />,
      },
      {
        title: "Event 2",
        path: "/events/events2",
        icon: <IoIcons.IoIosPaper />,
      },
    ],
  },
  {
    title: "Support",
    path: "/support",
    icon: <IoIcons.IoMdHelpCircle />,
  },
];

Filename- SubMenu.js: The logic for Dropdown links, again done with useState() hooks.

We create a state with the first element subnav as an initial state having a value of the false and the second element as function setSubnav() for updating the state. Then a function is created by the name showSubnav() which sets the value of subnav opposite to its present value whenever it is called.

This function is used with the open icon and close icon. When we click on the open icon to see the dropdown links it sets the value of the state to true, displays the dropdown menu and a close icon appears in place of the open icon. When we want to close the dropdown links we simply click on the close icon and it gets replaced with an open icon after closing the dropdown menu because now the value of the state is set to false.

As every sidelink is not having a dropdown menu, it first checks if a sideline has a property of subNav defined with it from the object array that we made in the SidebarData.js file. If that property exists then it executes the above logic otherwise the sidelinks appear normally without any open and close icons.

Javascript




import React, { useState } from "react";
import { Link } from "react-router-dom";
import styled from "styled-components";
  
const SidebarLink = styled(Link)`
  display: flex;
  color: #e1e9fc;
  justify-content: space-between;
  align-items: center;
  padding: 20px;
  list-style: none;
  height: 60px;
  text-decoration: none;
  font-size: 18px;
  
  &:hover {
    background: #252831;
    border-left: 4px solid green;
    cursor: pointer;
  }
`;
  
const SidebarLabel = styled.span`
  margin-left: 16px;
`;
  
const DropdownLink = styled(Link)`
  background: #252831;
  height: 60px;
  padding-left: 3rem;
  display: flex;
  align-items: center;
  text-decoration: none;
  color: #f5f5f5;
  font-size: 18px;
  
  &:hover {
    background: green;
    cursor: pointer;
  }
`;
  
const SubMenu = ({ item }) => {
  const [subnav, setSubnav] = useState(false);
  
  const showSubnav = () => setSubnav(!subnav);
  
  return (
    <>
      <SidebarLink to={item.path} 
      onClick={item.subNav && showSubnav}>
        <div>
          {item.icon}
          <SidebarLabel>{item.title}</SidebarLabel>
        </div>
        <div>
          {item.subNav && subnav
            ? item.iconOpened
            : item.subNav
            ? item.iconClosed
            : null}
        </div>
      </SidebarLink>
      {subnav &&
        item.subNav.map((item, index) => {
          return (
            <DropdownLink to={item.path} key={index}>
              {item.icon}
              <SidebarLabel>{item.title}</SidebarLabel>
            </DropdownLink>
          );
        })}
    </>
  );
};
  
export default SubMenu;

Now we are completed with the components folder now we manipulate the pages. Edit various pages for the sidebar in the project in src/pages:

Filename- AboutUs.js:

Javascript




import React from "react";
  
export const AboutUs = () => {
  return (
    <div className="home">
      <h1>GeeksforGeeks About us</h1>
    </div>
  );
};
  
export const OurAim = () => {
  return (
    <div className="home">
      <h1>GeeksforGeeks Aim</h1>
    </div>
  );
};
  
export const OurVision = () => {
  return (
    <div className="home">
      <h1>GeeksforGeeks Vision</h1>
    </div>
  );
};

Filename- ContactUs.js:

Javascript




import React from "react";
  
const Contact = () => {
  return (
    <div className="contact">
      <h1>GeeksforGeeks Contact us</h1>
    </div>
  );
};
  
export default Contact;

Filename- Events.js:

Javascript




import React from "react";
  
export const Events = () => {
  return (
    <div className="events">
      <h1>GeeksForGeeks Events</h1>
    </div>
  );
};
  
export const EventsOne = () => {
  return (
    <div className="events">
      <h1>GeeksforGeeks Event1</h1>
    </div>
  );
};
  
export const EventsTwo = () => {
  return (
    <div className="events">
      <h1>GeeksforGeeks Event2</h1>
    </div>
  );
};

Filename- Services.js:

Javascript




import React from "react";
  
export const Services = () => {
  return (
    <div className="services">
      <h1>GeeksforGeeks Services</h1>
    </div>
  );
};
  
export const ServicesOne = () => {
  return (
    <div className="services">
      <h1>GeeksforGeeks Service1</h1>
    </div>
  );
};
  
export const ServicesTwo = () => {
  return (
    <div className="services">
      <h1>GeeksforGeeks Service2</h1>
    </div>
  );
};
  
export const ServicesThree = () => {
  return (
    <div className="services">
      <h1>GeeksforGeeks Service3</h1>
    </div>
  );
};

Filename- Support.js:

Javascript




import React from "react";
  
const Support = () => {
  return (
    <div className="support">
      <h1>GeeksforGeeks Support us</h1>
    </div>
  );
};
  
export default Support;

All the pages and components are ready now we have to call them one by one in our App.js file.

Filename- App.js:

Javascript




import "./App.css";
import Sidebar from "./components/Sidebar";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import { AboutUs, OurAim, OurVision } from "./pages/AboutUs";
import {
  Services,
  ServicesOne,
  ServicesTwo,
  ServicesThree,
} from "./pages/Services";
import { Events, EventsOne, EventsTwo } from "./pages/Events";
import Contact from "./pages/ContactUs";
import Support from "./pages/Support";
function App() {
  return (
    <Router>
      <Sidebar />
      <Switch>
        <Route path="/about-us" exact component={AboutUs} />
        <Route path="/about-us/aim" exact component={OurAim} />
        <Route path="/about-us/vision" exact component={OurVision} />
        <Route path="/services" exact component={Services} />
        <Route path="/services/services1" exact component={ServicesOne} />
        <Route path="/services/services2" exact component={ServicesTwo} />
        <Route path="/services/services3" exact component={ServicesThree} />
        <Route path="/contact" exact component={Contact} />
        <Route path="/events" exact component={Events} />
        <Route path="/events/events1" exact component={EventsOne} />
        <Route path="/events/events2" exact component={EventsTwo} />
        <Route path="/support" exact component={Support} />
      </Switch>
    </Router>
  );
}
  
export default App;

Filename- App.css: modify the CSS according to you.

HTML




* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
.home,
.services,
.reports,
.contact,
.events,
.support {
  display: flex;
  margin-left: 260px;
  font-size: 2rem;
}

Run the Project: Save all files and start the server by using the below command.

npm start

Output:

My Personal Notes arrow_drop_up
Recommended Articles
Page :