How to Create Multi Level Sidebar Animation in React ?
Last Updated :
29 Jul, 2024
In this article, we will see how we can animate the Multi-level sidebar in ReactJS to enhance the overall appearance of the Sidebar component in the application. This attracts the user towards the interface more and also increases the look and feel of the application.
We will discuss the following two approaches to implement Multi Level Sidebar Animation in React.
Steps to Create the React Application:
Step 1: Create a React application using the following command.
npx create-react-app foldername
Step 2: Once done, change your directory to the newly created application using the following command.
cd foldername
Step 3: Install the required packages by executing the below command in the terminal.
npm install framer-motion react-icons
Project Structure:

The updated dependencies in package.json for a frontend will look like this:
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4",
"framer-motion": "^10.17.6",
"react-icons": "^4.12.0"
}
Approach 1: Using framer-motion
In this approach, we are using the Framer Motion animation where we have specified the state management to control the toggling of the sidebar, also we are performing the UI animation on the sidebar contents.
Example 1: Below is the implementation of above discussed approach.
CSS
body {
margin: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
display: flex;
height: 100vh;
overflow: hidden;
background-color: #f0f0f0;
}
.app {
display: flex;
flex: 1;
}
.sidebar {
width: 60px;
background-color: #333;
color: white;
padding: 20px;
display: flex;
flex-direction: column;
overflow: hidden;
}
.logo {
color: #4caf50;
font-size: 24px;
margin-bottom: 20px;
transition: font-size 0.5s ease;
}
.approach-title {
margin-bottom: 20px;
}
.sidebar-item {
cursor: pointer;
margin-bottom: 10px;
transition: background-color 0.3s ease;
}
.sidebar-item.active {
background-color: #555;
}
.sub-items {
overflow: hidden;
}
.sub-item {
padding-left: 20px;
margin-top: 5px;
cursor: pointer;
}
.toggle-button {
cursor: pointer;
background-color: #4caf50;
color: white;
border: none;
padding: 10px;
margin-top: 20px;
border-radius: 5px;
outline: none;
transition: margin-top 0.5s ease;
}
.sidebar-open .sidebar {
width: 300px;
}
.sidebar-open .logo {
font-size: 18px;
}
.sidebar-open .toggle-button {
margin-top: 30px;
}
.sidebar-open .sub-item {
padding-left: 20px;
}
.sidebar:not(.sidebar-open) {
overflow: hidden;
width: 400px;
transition: width 0.5s ease;
}
.sidebar:not(.sidebar-open) .toggle-button {
margin-top: 0;
}
.sidebar:not(.sidebar-open) .sub-item {
padding-left: 10;
}
.content {
flex: 1;
padding: 20px;
background-color: #fff;
overflow-y: auto;
}
.content-title {
color: #333;
font-size: 32px;
margin-bottom: 10px;
}
.content-subtitle {
color: #555;
font-size: 18px;
margin-bottom: 20px;
}
JavaScript
//App.js
import React, { useState } from "react";
import { motion } from "framer-motion";
import "./App.css";
const dataSide = [
{
id: 1,
title: "Home",
subItems: [],
},
{
id: 2,
title: "Topics",
subItems: [
{ id: 21, title: "React" },
{ id: 22, title: "JavaScript" },
{ id: 23, title: "CSS" },
],
},
{
id: 3,
title: "About",
subItems: [
{ id: 31, title: "GeeksforGeeks" },
{ id: 32, title: "Team" },
],
},
{
id: 4,
title: "More",
subItems: [
{ id: 41, title: "Animations" },
{ id: 42, title: "Components" },
],
},
];
const App = () => {
const [item_Select, set_Item_Select] = useState(null);
const [sideBar_Open, set_SideBar_Open] = useState(false);
const dataClickFn = (i) => {
set_Item_Select(i.id === item_Select?.id ? null : i);
};
const sideBarFn = () => {
set_SideBar_Open(!sideBar_Open);
};
return (
<div className={`app ${sideBar_Open ? "sidebar-open" : ""}`}>
<div className="sidebar">
{sideBar_Open && (
<>
<h1 className="logo">GeeksforGeeks</h1>
<motion.div
className="approach-title"
animate={{ opacity: 1, y: 0 }}
initial={{ opacity: 0, y: -20 }}
>
<h3>Approach 1: Using Framer Motion</h3>
</motion.div>
{dataSide.map((item) => (
<motion.div
key={item.id}
className={`sidebar-item ${
item_Select?.id === item.id ? "active" : ""
}`}
onClick={() => dataClickFn(item)}
whileHover={{ scale: 1.1 }}
>
{item.title}
{item.subItems.length > 0 && (
<motion.div
initial={false}
animate={{
height:
item_Select?.id === item.id
? "auto"
: 0,
}}
className="sub-items"
>
{item.subItems.map((subItem) => (
<motion.div
key={subItem.id}
className="sub-item"
>
{subItem.title}
</motion.div>
))}
</motion.div>
)}
</motion.div>
))}
</>
)}
<motion.button
className="toggle-button"
whileHover={{ scale: 1.1 }}
onClick={sideBarFn}
>
{sideBar_Open ? "Close Sidebar" : "Open Sidebar"}
</motion.button>
</div>
<div className="content">
<motion.h1
className="content-title"
animate={{ opacity: 1, y: 0 }}
initial={{ opacity: 0, y: -20 }}
>
Welcome to GeeksforGeeks
</motion.h1>
<motion.h3
className="content-subtitle"
animate={{ opacity: 1, y: 0 }}
initial={{ opacity: 0, y: -20 }}
>
Explore our amazing content
</motion.h3>
</div>
</div>
);
};
export default App;
Step to run the application: Open the terminal and type the following command.
npm start
Output: Open the browser and our project is shown in the URL http://localhost:3000/
Approach 2: Using CSS Only
In this approach, we are animating the multilevel sidebar by using CSS styling properties and keyframes. We are not using any other animation package like Approach 1. We have created all the animations by using CSS properties only.
Example 1: Below is the implementation of above discussed approach.
CSS
.app {
display: flex;
height: 100vh;
overflow: hidden;
}
.sidebar {
width: 200px;
background: linear-gradient(to right, #3f3f3f, #1a1a1a);
color: white;
padding: 20px;
transition: width 0.3s ease, box-shadow 0.3s ease;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3);
}
.sidebar-item {
cursor: pointer;
margin-bottom: 10px;
transition: all 0.3s ease;
position: relative;
animation: bounce 0.5s ease;
}
@keyframes bounce {
0%,
20%,
50%,
80%,
100% {
transform: translateY(0);
}
40% {
transform: translateY(-10px);
}
60% {
transform: translateY(-5px);
}
}
.sidebar-item span {
display: inline-block;
transition: transform 0.3s ease, text-shadow 0.3s ease;
}
.sidebar-item:hover {
margin-left: 10px;
box-shadow: 5px 0px 15px rgba(0, 0, 0, 0.3);
background: linear-gradient(to right, #555, #444);
border-radius: 10px;
color: #ffeb3b;
}
.sidebar-item:hover span {
transform: translateX(5px);
text-shadow: 2px 2px 5px rgba(255, 255, 255, 0.5);
}
.sidebar-item:after {
content: '';
display: block;
height: 2px;
width: 0;
background: rgb(224, 0, 0);
transition: width 0.3s ease;
}
.sidebar-item:hover:after {
width: 100%;
}
.open {
font-weight: bold;
}
.sub-menu {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease, opacity 0.3s ease;
animation: fadeIn 0.5s ease;
}
.sidebar-item.open .sub-menu {
max-height: 500px;
opacity: 1;
}
.sub-menu-item {
opacity: 0;
transform: translateY(-10px);
transition: opacity 0.5s ease, transform 0.5s ease;
color: #4caf50;
}
.sub-menu-item.show {
opacity: 1;
transform: translateY(0);
}
@media screen and (max-width: 768px) {
.app {
flex-direction: column;
}
.sidebar {
width: 100%;
position: absolute;
left: -100%;
transition: left 0.3s ease;
}
.sidebar.open {
left: 0;
}
.sidebar-item {
margin-left: 0;
}
.content {
opacity: 0;
transition: opacity 0.3s ease;
}
.content.open {
opacity: 1;
}
.hamburger {
display: block;
cursor: pointer;
order: -1;
}
}
.sidebar.open {
width: 250px;
}
.content {
color: green;
flex: 1;
padding: 20px;
background-color: #f4f4f4;
}
JavaScript
// App.js
import React, { useState } from "react";
import { FaHome, FaBook, FaLaptop, FaBookOpen, FaTools } from "react-icons/fa";
import { BsFillCaretDownFill } from "react-icons/bs";
import "./App.css";
const SidebarItem = ({ item, onClick }) => {
const [isOpen, setIsOpen] = useState(false);
const itemClickFn = () => {
setIsOpen(!isOpen);
if (onClick) {
onClick(item);
}
};
const getIcon = (label) => {
const iconMap = {
Home: <FaHome />,
Topics: <FaBook />,
Languages: <FaLaptop />,
About: <FaBookOpen />,
Frameworks: <FaTools />,
};
return iconMap[label] || <BsFillCaretDownFill />;
};
return (
<div
className={`sidebar-item ${isOpen ? "open" : ""}`}
onClick={itemClickFn}
>
<span className="icon">{getIcon(item.label)}</span>
<span>{item.label}</span>
{isOpen && item.children && (
<div className="sub-menu">
{item.children.map((child, index) => (
<SidebarItem key={index} item={child} />
))}
</div>
)}
</div>
);
};
const App = () => {
const data = [
{ label: "Home" },
{
label: "Topics",
children: [
{ label: "React" },
{ label: "JavaScript" },
{ label: "CSS" },
],
},
{
label: "Languages",
children: [
{
label: "Front-end",
children: [
{ label: "HTML" },
{ label: "CSS" },
{ label: "JavaScript" },
],
},
{
label: "Back-end",
children: [
{ label: "Node.js" },
{ label: "Python" },
{ label: "Ruby" },
],
},
],
},
{ label: "About" },
{
label: "Frameworks",
children: [
{ label: "React" },
{ label: "Angular" },
{ label: "Vue.js" },
],
},
];
return (
<div className="app">
<div className="sidebar">
{data.map((item, index) => (
<SidebarItem key={index} item={item} />
))}
</div>
<div className="content">
<h1>GeeksforGeeks</h1>
<h3>Approach 2: Using CSS Only</h3>
</div>
</div>
);
};
export default App;
Step to run the application: Open the terminal and type the following command.
npm start
Output: Open the browser and our project is shown in the URL http://localhost:3000/
Similar Reads
How to create Accordion in ReactJS ? Accordions contain creation flows and allow lightweight editing of an element. Material UI for React has this component available for us, and it is very easy to integrate. We can create it in React using the following approach.Approach to create Accordion in React JSTo create accordion in react we w
2 min read
How to create a Scroll To Bottom button in React JS ? Learn to implement a "Scroll to Bottom" button in React using the useState() hook, a feature commonly seen in chat applications like WhatsApp and Telegram for effortless navigation to the end of a chat window. Prerequisites:NodeJS or NPMReact JSstyled-componentReact useState()Steps to Create the Rea
2 min read
Exploring React Reveal: Creating Stunning Animations in React React Reveal is an animation library for React. In this article, we will see few of the implementation of this library and learn more about it.We will discuss the following two approaches:Table of ContentUsing the Fade EffectUsing the slide EffectCombining Animation and SequencePrerequisitesJavaScri
2 min read
How to Create a Sidebar in NextJS & Tailwind CSS? In web development, sidebars are commonly used to organize navigation elements and provide quick access to different sections of a website. A sidebar is a vertical menu or panel that is typically positioned on the left or right side of the main content area. Prerequisites:Next.jsTailwindJavaScriptSt
5 min read
How to create Tabs in ReactJS ? Tabs make it easy to explore and switch between different views. Material UI for React has this component available for us and it is very easy to integrate. We can use Tabs Component in ReactJS using the following approach.Prerequisites:NPM & Node.jsReact JSMaterial UIwe have these approaches to
4 min read
How to use Slide Component in ReactJS ? Slide Component adds a Slide animation to a child element or component. Material UI for React has this component available for us, and it is very easy to integrate. We can use the Slide Component in ReactJS using the following approach.Prerequisites:NodeJS or NPMReactJSMaterial UISteps to Create the
3 min read
How to trigger animations in a ReactJS app based on the scroll position ? To trigger animations in a ReactJS app based on the scroll position we can define multiple component animations for the scroll values provided by windows.scrollY. When we scroll to that defined position, some animations get triggered. This provides a very nice user experience.Prerequisite:Â React JSN
4 min read
How to create card animation using React Transition Group ? Creating card animation using React Transition Group simply refers to displaying animations in the card when any DOM event occurs. React transition group provide simple and easy-to-use components to display animation in the React components.Prerequisites:React JSNPM and Node.jsReact JS Transition Gr
3 min read
How to lift state two levels up in ReactJS ? We want to lift the state two levels up such that when an event occurs at the lower level component then it should affect the state two levels up. For example, there are three components X, Y, and Z. X is the parent of Component Y, and Component Y is the parent of Component Z. Prerequisites:NodeJS o
2 min read
React Suite Container Sidebar Layout React Suite is a library of React components, sensible UI design, and a friendly development experience. It is supported in all major browsers. It provides pre-built components of React which can be used easily in any web application. In this article, we'll learn about React Suite Container Sidebar
4 min read