npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@excel-pros/sidebar-library

v1.0.0

Published

Dynamic sidebar library for React + TailwindCSS

Readme

React Dynamic Sidebar

A highly customizable, responsive sidebar component for React applications with dynamic routing, collapsible navigation, and mobile-first design.

Features

  • 🎨 Fully Customizable - Complete control over styling and theming (no built-in themes)
  • 📱 Mobile Responsive - Touch gestures, swipe support, and adaptive layouts
  • 🎯 Dynamic Routing - Works with React Router or vanilla React routing
  • 🔧 Flexible Structure - Support for nested menus, groups, and custom components
  • 🎛️ Context API - Global sidebar state management
  • 📦 Zero Dependencies - Only requires React and Lucide React for icons
  • 🔄 Browser History - Seamless integration with browser back/forward buttons
  • 👆 Touch Friendly - Optimized for mobile with swipe gestures and touch interactions
  • Smooth Animations - Configurable transitions and micro-interactions
  • 🎨 CSS-in-JS Ready - Works with any styling solution (Tailwind, Styled Components, CSS Modules, etc.)

Installation

npm install @excelpros/sidebar-library
# or
yarn add @excelpros/sidebar-library

Peer Dependencies

For React Router integration:

npm install react-router-dom
# or
yarn add react-router-dom

Quick Start

Basic Implementation (Vanilla React)

import React, { useState, useEffect } from 'react';
import { 
  Sidebar, 
  SidebarLayout, 
  DynamicSidebarMenu,
  SidebarFooter 
} from 'react-dynamic-sidebar';
import { Home, Settings, User, Menu, ChevronLeft } from 'lucide-react';

function App() {
  const [currentPath, setCurrentPath] = useState(window.location.pathname);
  
  const handleNavigate = (path) => {
    setCurrentPath(path);
    window.history.pushState({}, "", path);
  };

  // Handle browser back/forward
  useEffect(() => {
    const onPopState = () => setCurrentPath(window.location.pathname);
    window.addEventListener("popstate", onPopState);
    return () => window.removeEventListener("popstate", onPopState);
  }, []);

  // Define your navigation structure (user-defined)
  const menuItems = [
    {
      type: "group",
      label: "Main",
      items: [
        {
          label: "Home",
          icon: Home,
          path: "/",
          className: "px-3 py-2 rounded-md hover:bg-blue-100",
        },
        {
          label: "Settings",
          icon: Settings,
          className: "px-3 py-2 rounded-md hover:bg-gray-100",
          children: [
            {
              label: "Profile",
              icon: User,
              path: "/settings/profile",
              className: "px-3 py-2 rounded-md hover:bg-green-100",
            }
          ]
        }
      ]
    }
  ];

  // Component mapping for routing (user-defined)
  const componentMap = {
    "/": () => <div className="p-6">🏠 Home Page</div>,
    "/settings/profile": () => <div className="p-6">👤 Profile Settings</div>,
  };

  const userData = { 
    name: "John Doe", 
    role: "Admin", 
    avatar: "/avatar.jpg" 
  };

  const ActiveComponent = componentMap[currentPath] || 
    (() => <div>Page not found</div>);

  return (
    <SidebarLayout
      navbar={<div className="bg-gray-100 p-4 border-b">Navigation Bar</div>}
      sidebar={
        <Sidebar
          title="My Company"
          logo="/logo.png"
          menuIcon={Menu}
          closeIcon={ChevronLeft}
          sidebarColor="bg-white"
          footer={
            <SidebarFooter 
              user={userData} 
              onLogout={() => alert("Logged out!")} 
            />
          }
        >
          <DynamicSidebarMenu 
            items={menuItems}
            currentPath={currentPath}
            onNavigate={handleNavigate}
          />
        </Sidebar>
      }
    >
      <ActiveComponent onNavigate={handleNavigate} />
    </SidebarLayout>
  );
}

React Router Integration

For applications using React Router, the integration is even simpler:

import { SidebarLayout, Sidebar, DynamicSidebarMenu } from "react-dynamic-sidebar";
import { Routes, Route, useNavigate, useLocation } from "react-router-dom";
import { Menu, ChevronLeft, Home, Settings, User } from "lucide-react";

function App() {
  const navigate = useNavigate();
  const location = useLocation();

  const handleNavigate = (path) => {
    navigate(path); // React Router handles the navigation
  };

  // Define your navigation structure (user customizable)
  const menuItems = [
    {
      type: "group",
      label: "Overview", 
      items: [
        {
          label: "Home",
          icon: Home,
          path: "/",
          className: "px-3 py-2 rounded-md hover:bg-blue-100",
        },
        {
          label: "Dashboard",
          icon: Settings,
          path: "/dashboard",
          className: "px-3 py-2 rounded-md hover:bg-green-100",
        }
      ]
    },
    {
      type: "group",
      label: "Settings",
      items: [
        {
          label: "Settings",
          icon: Settings,
          className: "px-3 py-2 rounded-md hover:bg-gray-100",
          children: [
            {
              label: "Profile", 
              icon: User,
              path: "/settings/profile",
              className: "px-3 py-2 rounded-md hover:bg-purple-100",
            },
            {
              label: "Security",
              icon: User, 
              path: "/settings/security",
              className: "px-3 py-2 rounded-md hover:bg-red-100",
            }
          ]
        }
      ]
    }
  ];

  // Page components (user-defined)
  const Home = () => <div className="p-6 text-xl">🏠 Home Page</div>;
  const Profile = () => <div className="p-6 text-xl">👤 Profile Settings</div>;
  const Security = () => <div className="p-6 text-xl">🔒 Security Settings</div>;

  // Map paths to components for route generation
  const routeComponentMap = {
    "/": Home,
    "/dashboard": () => <div className="p-6 text-xl">📊 Dashboard</div>,
    "/settings/profile": Profile,
    "/settings/security": Security,
  };

  return (
    <SidebarLayout
      navbar={<div className="bg-gray-100 p-4 border-b">Top Navigation</div>}
      sidebar={
        <Sidebar
          title="My Company"
          logo="/logo.png"
          menuIcon={Menu}
          closeIcon={ChevronLeft}
        >
          <DynamicSidebarMenu
            items={menuItems}
            currentPath={location.pathname}
            onNavigate={handleNavigate}
          />
        </Sidebar>
      }
    >
      <Routes>
        {Object.entries(routeComponentMap).map(([path, Component]) => (
          <Route key={path} path={path} element={<Component />} />
        ))}
        <Route path="*" element={<div className="p-6">404 - Not Found</div>} />
      </Routes>
    </SidebarLayout>
  );
}

Components

Sidebar

The main sidebar container with extensive customization options.

<Sidebar
  // Layout
  width="220px"
  collapsedWidth="60px"
  mobileWidth="200px"
  initialCollapsed={false}
  
  // Branding
  title="My Application"
  logo="/logo.png"
  
  // Navigation
  currentPath="/dashboard"
  onNavigate={(path) => console.log('Navigate to:', path)}
  
  // Mobile settings
  mobileSettings={{
    swipeToClose: true,
    backdropClick: true,
    autoClose: false,
    slideDirection: "left"
  }}
  
  // Styling
  sidebarColor="bg-white"
  animations={{
    enabled: true,
    duration: 300,
    sidebar: { width: true, transform: true }
  }}
>
  {/* Sidebar content */}
</Sidebar>

DynamicSidebarMenu

Renders navigation items from a configuration object.

const menuItems = [
  {
    type: "group",
    label: "Navigation",
    items: [
      {
        label: "Dashboard",
        icon: Home,
        path: "/dashboard"
      },
      {
        label: "Settings",
        icon: Settings,
        children: [
          {
            label: "Profile",
            icon: User,
            path: "/settings/profile"
          }
        ]
      }
    ]
  }
];

<DynamicSidebarMenu 
  items={menuItems}
  currentPath={currentPath}
  onNavigate={handleNavigate}
/>

SidebarMenuItem

Individual menu item component for custom implementations.

<SidebarMenuItem
  icon={Home}
  label="Dashboard"
  href="/dashboard"
  currentPath={currentPath}
  onNavigate={handleNavigate}
  className="custom-menu-item"
/>

SidebarLayout

Layout wrapper that manages sidebar and main content positioning.

<SidebarLayout
  sidebar={<Sidebar>...</Sidebar>}
  navbar={<Navbar />} // Optional
>
  <main>Your main content</main>
</SidebarLayout>

SidebarFooter

Customizable footer component for user info and actions.

<SidebarFooter
  user={{
    name: "John Doe",
    role: "Admin",
    avatar: "/avatar.jpg"
  }}
  onLogout={() => console.log('Logout')}
/>

Styling & Themes

The sidebar components are fully customizable with your own CSS classes and styling:

<SidebarMenuItem
  icon={Home}
  label="Dashboard"
  path="/dashboard"
  // Custom styling (user-defined)
  className="px-4 py-3 rounded-lg hover:bg-blue-50 transition-colors"
  iconClassName="text-blue-600 group-hover:text-blue-700"
  collapsedClassName="p-3 rounded-full hover:bg-gray-100"
  childrenClassName="ml-6 border-l-2 border-gray-200"
/>

Menu Item Structure

Each menu item can be customized with your preferred styling:

const menuItems = [
  {
    type: "group",
    label: "Navigation",
    className: "mb-4", // Custom group styling
    items: [
      {
        label: "Dashboard",
        icon: Home,
        path: "/dashboard",
        // Apply your own styles
        className: "px-4 py-2 rounded-md hover:bg-indigo-100 text-gray-700",
        iconClassName: "text-indigo-500",
        collapsedClassName: "p-2 rounded-full hover:bg-indigo-50"
      },
      {
        label: "Settings",
        icon: Settings,
        className: "px-4 py-2 rounded-md hover:bg-gray-100",
        children: [
          {
            label: "Profile",
            icon: User,
            path: "/profile",
            className: "px-3 py-2 ml-4 rounded hover:bg-green-50 text-sm",
            iconClassName: "text-green-600"
          }
        ]
      }
    ]
  }
];

Sidebar Styling

Customize the main sidebar appearance:

<Sidebar
  // Background and colors
  sidebarColor="bg-gradient-to-b from-blue-900 to-blue-800"
  sidebarBorderColor="#1e40af"
  
  // Logo and branding
  title="My App"
  logo="/logo.png"
  logoSize={{ 
    mobile: { expanded: 40, collapsed: 28 }, 
    desktop: { expanded: 60, collapsed: 40 } 
  }}
  
  // Custom styling
  className="shadow-2xl"
>
  {/* Your menu items */}
</Sidebar>

Mobile Features

The sidebar includes comprehensive mobile support:

  • Touch Gestures: Swipe to open/close
  • Backdrop Dismiss: Tap outside to close
  • Responsive Breakpoints: Automatic mobile/tablet detection
  • Slide Directions: Left, right, top, bottom slide animations
<Sidebar
  mobileSettings={{
    swipeToClose: true,
    backdropClick: true,
    autoClose: true, // Auto-close after navigation
    slideDirection: "left",
    overlayOpacity: 0.4,
    swipeThreshold: 50
  }}
  breakpoints={{
    mobile: 768,
    tablet: 1024
  }}
/>

Animation Configuration

Highly customizable animation system:

<Sidebar
  animations={{
    enabled: true,
    duration: 300,
    easing: "ease-in-out",
    sidebar: {
      width: true,
      transform: true,
      opacity: false
    },
    icons: {
      rotation: true,
      scale: true,
      opacity: true
    },
    menuItems: {
      stagger: true,
      slideIn: true,
      delay: 50
    },
    effects: {
      glow: false,
      shake: false,
      pulse: false
    }
  }}
/>

Context API

Use the sidebar context for global state management:

import { SidebarProvider, useSidebar } from 'react-dynamic-sidebar';

function App() {
  return (
    <SidebarProvider initialCollapsed={false}>
      <MyComponent />
    </SidebarProvider>
  );
}

function MyComponent() {
  const { collapsed, toggle } = useSidebar();
  
  return (
    <button onClick={toggle}>
      {collapsed ? 'Expand' : 'Collapse'} Sidebar
    </button>
  );
}

Advanced Usage

Routing Integration

Vanilla React (Manual Routing)

For applications without React Router, use manual route handling:

import React, { useState, useEffect } from 'react';

function App() {
  const [currentPath, setCurrentPath] = useState(window.location.pathname);
  
  const handleNavigate = (path) => {
    setCurrentPath(path);
    window.history.pushState({}, "", path);
  };

  // Handle browser back/forward
  useEffect(() => {
    const onPopState = () => setCurrentPath(window.location.pathname);
    window.addEventListener("popstate", onPopState);
    return () => window.removeEventListener("popstate", onPopState);
  }, []);

  const componentMap = {
    "/": HomePage,
    "/settings": SettingsPage,
  };

  const ActiveComponent = componentMap[currentPath] || NotFoundPage;
  
  return (
    <SidebarLayout sidebar={sidebar}>
      <ActiveComponent />
    </SidebarLayout>
  );
}

React Router Integration

The sidebar works seamlessly with React Router:

import { useNavigate, useLocation, Routes, Route } from 'react-router-dom';

function App() {
  const navigate = useNavigate();
  const location = useLocation();

  const handleNavigate = (path) => {
    navigate(path); // React Router handles everything
  };

  return (
    <SidebarLayout
      sidebar={
        <Sidebar>
          <DynamicSidebarMenu
            items={menuItems}
            currentPath={location.pathname}
            onNavigate={handleNavigate}
          />
        </Sidebar>
      }
    >
      <Routes>
        <Route path="/" element={<HomePage />} />
        <Route path="/settings/*" element={<SettingsPage />} />
        <Route path="*" element={<NotFoundPage />} />
      </Routes>
    </SidebarLayout>
  );
}

Dynamic Route Generation

For cleaner code, generate routes dynamically:

const routeComponentMap = {
  "/": HomePage,
  "/dashboard": DashboardPage,
  "/settings/profile": ProfilePage,
  "/settings/security": SecurityPage,
};

// Generate routes automatically
<Routes>
  {Object.entries(routeComponentMap).map(([path, Component]) => (
    <Route key={path} path={path} element={<Component />} />
  ))}
  <Route path="*" element={<div>404 - Not Found</div>} />
</Routes>

Browser History Integration

The sidebar automatically integrates with browser history:

// Browser back/forward support
useEffect(() => {
  const onPopState = () => setCurrentPath(window.location.pathname);
  window.addEventListener("popstate", onPopState);
  return () => window.removeEventListener("popstate", onPopState);
}, []);

const handleNavigate = (path) => {
  setCurrentPath(path);
  window.history.pushState({}, "", path); // Updates browser URL
};

Custom Page Components

Define your page components and map them to routes:

// pages/Home.js
export default function Home({ onNavigate }) {
  return (
    <div className="p-6">
      <h1>Welcome to Dashboard</h1>
      <button onClick={() => onNavigate('/settings/profile')}>
        Go to Profile
      </button>
    </div>
  );
}

// componentMap.js
import Home from './pages/Home';
import Profile from './pages/Profile';
import Security from './pages/Security';

export const componentMap = {
  "/": Home,
  "/home": Home,
  "/settings/profile": Profile,
  "/settings/security": Security,
};

Props Reference

Sidebar Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | initialCollapsed | boolean | false | Initial collapsed state | | width | string | "220px" | Desktop sidebar width | | collapsedWidth | string | "60px" | Desktop collapsed width | | mobileWidth | string | "200px" | Mobile sidebar width |mobileCollapsedWidth|string|-|Mobile sidebar widht collapsed| | title | string | - | Sidebar title | | logo | string | - | Logo image path | | currentPath | string | - | Current active path | | onNavigate | function | - | Navigation callback | | mobileSettings | object | - | Mobile behavior configuration | | animations | object | - | Animation configuration | | sidebarColor | string | "bg-white" | Background color/class |

Menu Item Structure

Users define their own menu structure and styling:

interface MenuItem {
  // Basic properties
  type?: 'group';
  label: string;
  icon?: ComponentType;
  path?: string;
  children?: MenuItem[];
  items?: MenuItem[]; // For groups
  
  // Custom styling (user-defined)
  className?: string;           // Main item styling
  iconClassName?: string;       // Icon-specific styling  
  collapsedClassName?: string;  // Styling when sidebar is collapsed
  childrenClassName?: string;   // Styling for nested items
}

Example implementation:

const menuItems = [
  {
    type: "group",
    label: "Main",
    className: "mb-4 pb-2 border-b border-gray-200", // User's group styling
    items: [
      {
        label: "Dashboard",
        icon: Home,
        path: "/dashboard",
        // User defines their own styling
        className: "flex items-center px-4 py-2 rounded-lg hover:bg-blue-50 text-gray-700 transition-colors duration-200",
        iconClassName: "mr-3 text-blue-500 group-hover:text-blue-600",
        collapsedClassName: "p-3 rounded-full hover:bg-blue-100 group"
      }
    ]
  }
];

Browser Support

  • Chrome/Edge 88+
  • Firefox 85+
  • Safari 14+
  • Mobile browsers with touch support

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

MIT License - see the LICENSE file for details.

Changelog

v1.0.0

  • Initial release
  • Core sidebar functionality
  • Mobile responsiveness
  • Animation system
  • Theme presets
  • Context API integration