DEV Community

Cover image for From Zero to Hero: Building a Scalable React Admin Dashboard Layout
chintanonweb
chintanonweb

Posted on

From Zero to Hero: Building a Scalable React Admin Dashboard Layout

Building a Responsive React Admin Panel Layout

Introduction

In today’s digital landscape, building a user-friendly admin panel is crucial for managing applications effectively. This article will take you through the process of creating a responsive admin panel layout using React. We'll focus on building a Navbar for navigation, a collapsible Sidebar for menu options, and an AdminLayout to house these components, making it easy for beginners to understand. You will find demo link end of the article.


Step 1: Setting Up the Project

To start, ensure you have a React environment set up. If you haven't already, create a new React project using Create React App or your preferred setup method.

npx create-react-app admin-panel
cd admin-panel
Enter fullscreen mode Exit fullscreen mode

Step 2: Install React Router

To manage navigation in your admin panel, install React Router:

npm install react-router-dom
Enter fullscreen mode Exit fullscreen mode

Step 3: Create the Project Structure

Create the following folder structure to organize your components:

src/
|-- components/
|   |-- AdminLayout.js
|   |-- Navbar.js
|   |-- Sidebar.js
|   |-- SidebarItem.js
|-- constants/
|   |-- image.js
|-- App.js
|-- index.js
Enter fullscreen mode Exit fullscreen mode

Step 4: Create the Navbar Component

The Navbar will display the title of the admin panel and any notification or profile options.

// src/components/Navbar.js
import { useState } from "react";
import AllImages from "../../constants/image"; // Update the path as needed

const Navbar = () => {
  const [isDropdownOpen, setIsDropdownOpen] = useState(false);
  const toggleDropdown = () => setIsDropdownOpen(!isDropdownOpen);

  return (
    <header className="w-full bg-white shadow p-4 sticky top-0 z-10">
      <nav className="flex justify-between items-center">
        <div className="text-2xl font-bold">DMS System</div>
        <div className="flex items-center space-x-6">
          <button onClick={toggleDropdown} className="flex items-center space-x-2">
            <span className="font-medium">
              <AllImages.user />
            </span>
            <span className="hidden md:block font-medium">John Richard</span>
            <span className="font-medium">{/* Add dropdown arrow icon */}</span>
          </button>
          {isDropdownOpen && (
            <div className="absolute right-0 mt-4 w-48 bg-white shadow-md rounded-md z-10">
              <ul className="py-2">
                <li className="px-4 py-2 hover:bg-gray-100 cursor-pointer">Profile</li>
                <li className="px-4 py-2 hover:bg-gray-100 cursor-pointer">Settings</li>
                <li className="px-4 py-2 hover:bg-gray-100 cursor-pointer">Logout</li>
              </ul>
            </div>
          )}
        </div>
      </nav>
    </header>
  );
};

export default Navbar;
Enter fullscreen mode Exit fullscreen mode

Step 5: Create the Sidebar Component

The Sidebar will contain links to different admin sections and can be collapsed for better space management.

// src/components/Sidebar.js
import { useLocation } from "react-router-dom";
import SidebarItem from "./SidebarItem";
import AllImages from "../../constants/image"; // Update the path as needed

const Sidebar = ({ isCollapsed, toggleSidebar }) => {
  const sidebarItems = [
    { href: "/admin/home", label: "Dashboard", icon: <AllImages.dashboard /> },
    { href: "/admin/user-roles", label: "User Roles", icon: <AllImages.userRoles /> },
    { href: "/admin/user-management", label: "User Management", icon: <AllImages.userManagement /> },
    { href: "/admin/customers", label: "Customers", icon: <AllImages.customers /> },
    { href: "/admin/auto-response", label: "Auto Response", icon: <AllImages.autoResponse /> },
    { href: "/admin/subscriptions", label: "Subscriptions", icon: <AllImages.subscriptions /> },
  ];

  return (
    <aside className={`${isCollapsed ? "w-14" : "w-64"} h-full bg-gray-800 transition-all duration-300`}>
      <button onClick={toggleSidebar} className="absolute -right-2.5 top-0 w-6 h-6 flex justify-center items-center hover:bg-gray-300 rounded-full transition cursor-pointer">
        {/* Add toggle icon */}
      </button>
      <nav className="mt-4">
        <ul>
          {sidebarItems.map((item) => (
            <SidebarItem key={item.href} href={item.href} label={item.label} isCollapsed={isCollapsed} icon={item.icon} />
          ))}
        </ul>
      </nav>
    </aside>
  );
};

export default Sidebar;
Enter fullscreen mode Exit fullscreen mode

Step 6: Create the Sidebar Item Component

This component will represent each item in the sidebar menu.

// src/components/SidebarItem.js
import { Link, useLocation } from "react-router-dom";

const SidebarItem = ({ href, label, isCollapsed, icon }) => {
  const location = useLocation();
  const isActive = location.pathname === href;

  return (
    <li className={`group`}>
      <Link to={href} className={`flex items-center py-2.5 px-4 hover:bg-gray-700 transition ${isActive ? "bg-gray-700" : ""}`}>
        {icon}
        <span className={`text-white ml-4 ${isCollapsed ? "hidden" : "block"}`}>{label}</span>
      </Link>
    </li>
  );
};

export default SidebarItem;
Enter fullscreen mode Exit fullscreen mode

Step 7: Create the Admin Layout Component

This component will bring together the Navbar and Sidebar, along with the main content area.

// src/components/AdminLayout.js
import { useState } from "react";
import { Outlet } from "react-router-dom";
import Navbar from "./Navbar";
import Sidebar from "./Sidebar";

const AdminLayout = () => {
  const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(false);

  const toggleSidebar = () => setIsSidebarCollapsed(!isSidebarCollapsed);

  return (
    <div className="h-screen flex flex-col">
      <Navbar />
      <div className="flex flex-grow overflow-hidden">
        <Sidebar isCollapsed={isSidebarCollapsed} toggleSidebar={toggleSidebar} />
        <div className="flex-grow p-4 overflow-y-auto bg-gray-100">
          <Outlet />
        </div>
      </div>
    </div>
  );
};

export default AdminLayout;
Enter fullscreen mode Exit fullscreen mode

Step 8: Update the App Component

Finally, set up your routes in App.js to utilize the new layout.

// src/App.js
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import AdminLayout from "./components/AdminLayout";

const App = () => {
  return (
    <Router>
      <Routes>
        <Route path="/admin/*" element={<AdminLayout />}>
          {/* Define your nested routes here */}
          <Route path="home" element={<div>Home Page</div>} />
          <Route path="user-roles" element={<div>User Roles Page</div>} />
          <Route path="user-management" element={<div>User Management Page</div>} />
          <Route path="customers" element={<div>Customers Page</div>} />
          <Route path="auto-response" element={<div>Auto Response Page</div>} />
          <Route path="subscriptions" element={<div>Subscriptions Page</div>} />
        </Route>
      </Routes>
    </Router>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

Step 9: Constants for Icons

You may want to add placeholder icons in your constants/image.js file. Here's a simple example of how it might look:

// src/constants/image.js
const AllImages = {
  user: () => <svg>...</svg>, // Replace with your SVG or icon components
  dashboard: () => <svg>...</svg>,
  userRoles: () => <svg>...</svg>,
  userManagement: () => <svg>...</svg>,
  customers: () => <svg>...</svg>,
  autoResponse: () => <svg>...</svg>,
  subscriptions: () => <svg>...</svg>,
};

export default AllImages;
Enter fullscreen mode Exit fullscreen mode

Step 10: Styling

Ensure you have appropriate styling in your CSS files to reflect the layout. You can use Tailwind CSS or any other styling framework you prefer. Here's an example using Tailwind CSS:

/* Add this to your main CSS file or Tailwind config */
body {
  margin: 0;
  font-family: sans-serif;
}
Enter fullscreen mode Exit fullscreen mode

Sure! Let's continue from where we left off, with additional functionality and final steps for polishing your admin panel.


Step 11: Making Sidebar Collapsible

To make the Sidebar collapsible, you can toggle the isCollapsed state in AdminLayout.js. You already have the toggleSidebar function in place, which changes the width of the Sidebar between w-64 (expanded) and w-14 (collapsed). You can improve the UX by adding a smooth transition for the Sidebar and its content.

For the toggle button, you can use a simple icon like a chevron to indicate the action. Here’s how you might do it:

AdminLayout.js:

// src/components/AdminLayout.js
import { useState } from "react";
import { Outlet } from "react-router-dom";
import Navbar from "./Navbar";
import Sidebar from "./Sidebar";

const AdminLayout = () => {
  const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(false);

  const toggleSidebar = () => setIsSidebarCollapsed(!isSidebarCollapsed);

  return (
    <div className="h-screen flex flex-col">
      <Navbar />
      <div className="flex flex-grow overflow-hidden">
        <Sidebar isCollapsed={isSidebarCollapsed} toggleSidebar={toggleSidebar} />
        <div className={`flex-grow p-4 transition-all duration-300 ${isSidebarCollapsed ? "ml-14" : "ml-64"}`}>
          <Outlet />
        </div>
      </div>
    </div>
  );
};

export default AdminLayout;
Enter fullscreen mode Exit fullscreen mode

This ensures the main content shifts accordingly when the Sidebar is collapsed or expanded.

Step 12: Styling and Animations

You can improve the overall experience of your admin panel with some transitions and hover effects.

  • Sidebar transitions: To make the collapse/expand action smoother, you can add the transition-all and duration-300 classes in Tailwind CSS, which give the Sidebar a 300ms transition effect.

  • Hover effects: Add hover effects to the sidebar items so users know they can click on them. Update your SidebarItem component like this:

SidebarItem.js:

// src/components/SidebarItem.js
import { Link, useLocation } from "react-router-dom";

const SidebarItem = ({ href, label, isCollapsed, icon }) => {
  const location = useLocation();
  const isActive = location.pathname === href;

  return (
    <li className={`group`}>
      <Link 
        to={href} 
        className={`flex items-center py-2.5 px-4 hover:bg-gray-700 transition-all duration-300 
                    ${isActive ? "bg-gray-700" : ""}`}>
        {icon}
        <span className={`text-white ml-4 ${isCollapsed ? "hidden" : "block"} transition-all duration-300`}>
          {label}
        </span>
      </Link>
    </li>
  );
};

export default SidebarItem;
Enter fullscreen mode Exit fullscreen mode

This will make sure the Sidebar items have a smooth transition when collapsed, and a hover state for visual feedback.

Step 13: Adding Active Route Highlight

You can enhance the usability by highlighting the currently active route in the Sidebar. The above SidebarItem component already uses the isActive state to apply a background when the current route matches the href of the link.

const isActive = location.pathname === href;
Enter fullscreen mode Exit fullscreen mode

This line checks if the current route is the same as the href and applies the active background color.

Step 14: Dynamic Page Content (Outlet)

The AdminLayout component uses <Outlet /> to render the nested routes. This is useful when you want different content to be displayed in the main content area based on the route. You can define these routes in App.js like this:

App.js:

// src/App.js
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import AdminLayout from "./components/AdminLayout";

const App = () => {
  return (
    <Router>
      <Routes>
        <Route path="/admin/*" element={<AdminLayout />}>
          <Route path="home" element={<div>Home Page</div>} />
          <Route path="user-roles" element={<div>User Roles Page</div>} />
          <Route path="user-management" element={<div>User Management Page</div>} />
          <Route path="customers" element={<div>Customers Page</div>} />
          <Route path="auto-response" element={<div>Auto Response Page</div>} />
          <Route path="subscriptions" element={<div>Subscriptions Page</div>} />
        </Route>
      </Routes>
    </Router>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

In this example, each nested route (e.g., /admin/home, /admin/user-roles, etc.) corresponds to a different component or section within the admin panel. You can replace the <div> placeholders with actual components.

Step 15: Adding Real Content to Pages

You can replace the content placeholders (like <div>Home Page</div>) with more meaningful components, depending on your app’s requirements. For example, here’s a simple Home.js component:

Home.js:

// src/pages/Home.js
const Home = () => {
  return (
    <div>
      <h1 className="text-3xl font-bold mb-6">Dashboard Overview</h1>
      {/* Add dashboard content here */}
    </div>
  );
};

export default Home;
Enter fullscreen mode Exit fullscreen mode

Then update your route in App.js to point to this component:

import Home from "./pages/Home";

<Route path="home" element={<Home />} />
Enter fullscreen mode Exit fullscreen mode

You can follow this pattern for other pages (e.g., UserRoles.js, Customers.js).


Step 16: Responsive Design

To make the admin panel responsive, you can apply media queries or use Tailwind’s responsive utility classes. For example, to collapse the Sidebar automatically on smaller screens, you can update the Sidebar component like this:

<aside className={`${isCollapsed ? "w-14" : "w-64"} h-full bg-gray-800 transition-all duration-300 
                    md:block hidden`}>
Enter fullscreen mode Exit fullscreen mode

This ensures that the Sidebar is hidden on mobile devices by default, and you can add a button in the Navbar to toggle it when needed. You can use Tailwind’s responsive classes (md:block, hidden, etc.) to adjust the layout based on screen size.


Final Step: Testing and Polishing

Demo Link : Click Here

Before finishing up:

  1. Test responsiveness: Open your app in different screen sizes and ensure the layout adapts well.
  2. Optimize performance: If your app grows, make sure to implement lazy loading for routes and optimize components for performance.
  3. Code cleanup: Remove any unused code and ensure your codebase is organized and readable.

Conclusion

You now have a complete, responsive, and functional admin panel layout using React. With a collapsible Sidebar, dynamic content loading via Outlet, and smooth transitions, your admin panel is well-suited for managing various sections of an application. This structure is scalable, allowing you to add more pages and functionality as your application grows.

Top comments (0)