Sidebar

Component

Premium Tailwind sidebar components featuring glassmorphism, fluid collapsibility, and nested Tailwind CSS sidebar menus.

For complex applications and dashboards, a robust Tailwind sidebar provides the structural backbone necessary for deep navigation. These components feature seamless transitions, collapsible states, and organized Tailwind CSS sidebar menus built with premium, ultra-minimal aesthetics.

A strong sidebar is often paired with a top-level Header for global actions, and frequently utilizes an Avatar at the bottom to represent the current user's profile.

Basic Sleek Sidebar

import React, { useState } from "react";

const BasicSidebar = () => {
  const [activeItem, setActiveItem] = useState("Dashboard");

  return (
    <div className="flex flex-col w-64 bg-white dark:bg-neutral-950 h-screen justify-between border-r border-neutral-200/50 dark:border-white/10 shadow-[4px_0_24px_rgba(0,0,0,0.02)] dark:shadow-[4px_0_24px_rgba(0,0,0,0.2)]">
      <div className="overflow-y-auto pt-6 px-4">
        <div className="flex items-center px-4 mb-8">
          <div className="w-7 h-7 bg-neutral-900 dark:bg-white rounded-lg flex items-center justify-center mr-3 shadow-sm">
            <span className="text-white dark:text-neutral-900 font-bold text-[14px]">A</span>
          </div>
          <span className="font-semibold text-[16px] text-neutral-900 dark:text-white tracking-tight">
            Acme Inc.
          </span>
        </div>
        
        <div className="space-y-1 mt-6">
          <p className="px-4 text-[11px] font-semibold text-neutral-400 uppercase tracking-wider mb-2">Platform</p>
          {["Dashboard", "Projects", "Team", "Reports", "Settings"].map((item) => (
            <button
              key={item}
              className={`w-full flex items-center px-4 py-2.5 text-[14px] font-medium rounded-xl transition-all duration-200 border border-transparent ${
                activeItem === item
                  ? "bg-neutral-100 dark:bg-neutral-900 text-neutral-900 dark:text-white shadow-sm border-neutral-200/50 dark:border-white/5"
                  : "text-neutral-600 dark:text-neutral-400 hover:bg-neutral-50 dark:hover:bg-neutral-900/50"
              }`}
              onClick={() => setActiveItem(item)}
            >
              {item}
            </button>
          ))}
        </div>
      </div>

      <div className="p-4 mx-4 mb-4 mt-auto">
        <button className="w-full flex items-center gap-3 p-2 hover:bg-neutral-100 dark:hover:bg-neutral-900 rounded-xl transition-colors">
          <img
            className="object-cover rounded-full h-9 w-9 border border-neutral-200 dark:border-neutral-800 shadow-sm"
            src="https://i.pravatar.cc/150?img=32"
            alt="avatar"
          />
          <div className="flex flex-col text-left">
            <span className="text-[14px] font-semibold text-neutral-900 dark:text-white leading-tight">Sarah J.</span>
            <span className="text-[12px] text-neutral-500">sarah@acme.com</span>
          </div>
        </button>
      </div>
    </div>
  );
};

export default BasicSidebar;
import React, { useState } from "react";
import { Search, Home, LayoutDashboard, FolderOpen, Users, MessageSquare, PieChart, Settings } from "lucide-react";

const SidebarwithIcons = () => {
  const [activeItem, setActiveItem] = useState("Home");

  const menuItems = [
    { name: "Home", icon: Home },
    { name: "Dashboard", icon: LayoutDashboard },
    { name: "Projects", icon: FolderOpen },
    { name: "Team", icon: Users },
    { name: "Messages", icon: MessageSquare },
    { name: "Analytics", icon: PieChart },
  ];

  return (
    <div className="flex flex-col w-[260px] bg-neutral-50/50 dark:bg-[#0A0A0A] h-screen justify-between border-r border-neutral-200/60 dark:border-white/10">
      <div className="overflow-y-auto px-4 py-6">
        <div className="mb-6 relative">
          <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-neutral-400" />
          <input 
            type="text"
            placeholder="Search..."
            className="w-full bg-white dark:bg-neutral-900 border border-neutral-200 dark:border-neutral-800 rounded-xl py-2 pl-9 pr-4 text-[13px] outline-none focus:ring-2 focus:ring-neutral-200 dark:focus:ring-neutral-800 shadow-sm transition-all"
          />
        </div>

        <nav className="space-y-1.5">
          {menuItems.map((item) => {
            const isActive = activeItem === item.name;
            return (
              <button
                key={item.name}
                onClick={() => setActiveItem(item.name)}
                className={`w-full group flex items-center justify-between px-3 py-2.5 rounded-xl transition-all duration-300 ${
                  isActive
                    ? "bg-white dark:bg-neutral-900 shadow-sm border border-neutral-200/60 dark:border-white/10"
                    : "hover:bg-neutral-100 dark:hover:bg-neutral-900 border border-transparent"
                }`}
              >
                <div className="flex items-center gap-3">
                  <item.icon
                    className={`w-4 h-4 transition-colors duration-300 ${
                      isActive ? "text-neutral-900 dark:text-white" : "text-neutral-500 group-hover:text-neutral-700 dark:group-hover:text-neutral-300"
                    }`}
                    strokeWidth={isActive ? 2.5 : 2}
                  />
                  <span className={`text-[14px] font-medium transition-colors ${
                    isActive ? "text-neutral-900 dark:text-white" : "text-neutral-600 dark:text-neutral-400 group-hover:text-neutral-900 dark:group-hover:text-white"
                  }`}>
                    {item.name}
                  </span>
                </div>
                {item.name === "Messages" && (
                  <span className="bg-blue-500 text-white text-[10px] font-bold px-1.5 py-0.5 rounded-full">3</span>
                )}
              </button>
            )
          })}
        </nav>
      </div>

      <div className="p-4 border-t border-neutral-200/60 dark:border-white/10">
        <button className="w-full group flex items-center gap-3 px-3 py-2.5 rounded-xl hover:bg-neutral-100 dark:hover:bg-neutral-900 transition-colors">
          <Settings className="w-4 h-4 text-neutral-500 group-hover:text-neutral-700 dark:group-hover:text-neutral-300" strokeWidth={2} />
          <span className="text-[14px] font-medium text-neutral-600 dark:text-neutral-400 group-hover:text-neutral-900 dark:group-hover:text-white">Settings</span>
        </button>
      </div>
    </div>
  );
};

export default SidebarwithIcons;

Floating Island Sidebar

import React, { useState } from "react";
import { LayoutDashboard, PieChart, Users } from "lucide-react";

const FloatingIslandSidebar = () => {
  const [activeItem, setActiveItem] = useState("Layout");

  const menuItems = [
    { name: "Layout", icon: LayoutDashboard },
    { name: "Analytics", icon: PieChart },
    { name: "Community", icon: Users },
  ];

  return (
    <div className="h-screen bg-neutral-100 dark:bg-neutral-950 p-4 flex">
      <div className="flex flex-col w-[260px] bg-white/70 dark:bg-neutral-900/70 backdrop-blur-2xl border border-white dark:border-white/10 rounded-[28px] shadow-xl overflow-hidden h-full">
        <div className="p-6 pb-2">
          <div className="flex items-center gap-3">
            <div className="w-8 h-8 rounded-full bg-gradient-to-tr from-rose-500 to-orange-400 shadow-inner" />
            <span className="font-bold text-[15px] tracking-tight text-neutral-900 dark:text-white">Nexus</span>
          </div>
        </div>

        <div className="flex-1 overflow-y-auto p-4 space-y-2">
          {menuItems.map((item) => (
            <button
              key={item.name}
              onClick={() => setActiveItem(item.name)}
              className={`w-full flex items-center gap-3 px-4 py-3 rounded-2xl transition-all duration-300 ${
                activeItem === item.name
                  ? "bg-neutral-900 dark:bg-white text-white dark:text-neutral-900 shadow-md scale-[0.98]"
                  : "bg-transparent text-neutral-600 dark:text-neutral-400 hover:bg-white/50 dark:hover:bg-neutral-800/50"
              }`}
            >
              <item.icon className="w-[18px] h-[18px]" strokeWidth={activeItem === item.name ? 2.5 : 2} />
              <span className="text-[14px] font-semibold">{item.name}</span>
            </button>
          ))}
        </div>

        <div className="p-4 mt-auto">
          <div className="bg-neutral-100 dark:bg-neutral-950/50 rounded-2xl p-4 flex items-center justify-between border border-neutral-200/50 dark:border-white/5">
            <div className="flex flex-col items-start gap-1">
              <span className="text-[12px] font-bold text-neutral-900 dark:text-white">Pro Plan</span>
              <span className="text-[11px] text-neutral-500">4 days left</span>
            </div>
            <button className="text-[11px] font-semibold bg-white dark:bg-neutral-800 px-2 py-1 rounded-lg shadow-sm border border-neutral-200 dark:border-white/5">Upgrade</button>
          </div>
        </div>
      </div>
    </div>
  );
};

export default FloatingIslandSidebar;

Expandable Nested Sidebar

import React, { useState } from "react";
import { Home, Bell, FolderOpen, Users, ChevronDown } from "lucide-react";

const ExpandableNestedSidebar = () => {
  const [activeItem, setActiveItem] = useState("Overview");
  const [openGroups, setOpenGroups] = useState({
    Projects: true
  });

  const toggleGroup = (group) => {
    setOpenGroups(prev => ({ ...prev, [group]: !prev[group] }));
  };

  const menuStructure = [
    { type: 'item', name: "Overview", icon: Home },
    { type: 'item', name: "Notifications", icon: Bell, badge: 2 },
    { type: 'divider' },
    { 
      type: 'group', 
      name: "Projects", 
      icon: FolderOpen,
      items: ["Design System", "Marketing Site", "Mobile App"]
    },
    { 
      type: 'group', 
      name: "Team", 
      icon: Users,
      items: ["Developers", "Designers", "Management"]
    }
  ];

  return (
    <div className="flex flex-col w-[260px] bg-white dark:bg-[#0A0A0A] h-screen border-r border-neutral-200/60 dark:border-white/10 shadow-sm">
      <div className="p-6">
        <h2 className="text-[18px] font-semibold text-neutral-900 dark:text-white tracking-tight">Workspace</h2>
      </div>

      <div className="flex-1 overflow-y-auto px-4 space-y-1">
        {menuStructure.map((node, i) => {
          if (node.type === 'divider') {
            return <div key={i} className="h-px w-full bg-neutral-200/60 dark:bg-neutral-800/60 my-4" />
          }
          if (node.type === 'item') {
            const isActive = activeItem === node.name;
            return (
              <button
                key={node.name}
                onClick={() => setActiveItem(node.name)}
                className={`w-full flex items-center justify-between px-3 py-2 rounded-lg transition-colors ${
                  isActive ? "bg-blue-50 dark:bg-blue-500/10 text-blue-600 dark:text-blue-400 font-medium" : "text-neutral-600 dark:text-neutral-400 hover:bg-neutral-100 dark:hover:bg-neutral-900"
                }`}
              >
                <div className="flex items-center gap-3">
                  <node.icon className="w-4 h-4" />
                  <span className="text-[14px]">{node.name}</span>
                </div>
                {node.badge && <span className="bg-blue-100 dark:bg-blue-500/20 text-blue-600 dark:text-blue-400 text-[10px] font-bold px-1.5 py-0.5 rounded-full">{node.badge}</span>}
              </button>
            )
          }
          if (node.type === 'group') {
            const isOpen = openGroups[node.name];
            return (
              <div key={node.name} className="pt-2">
                <button
                  onClick={() => toggleGroup(node.name)}
                  className="w-full flex items-center justify-between px-3 py-2 text-neutral-600 dark:text-neutral-400 hover:bg-neutral-100 dark:hover:bg-neutral-900 rounded-lg transition-colors group"
                >
                  <div className="flex items-center gap-3">
                    <node.icon className="w-4 h-4" />
                    <span className="text-[14px] font-medium">{node.name}</span>
                  </div>
                  <ChevronDown className={`w-3.5 h-3.5 transition-transform duration-200 ${isOpen ? "rotate-180" : ""}`} />
                </button>
                
                <div className={`overflow-hidden transition-all duration-300 ease-in-out ${
                  isOpen ? "max-h-40 opacity-100 mt-1" : "max-h-0 opacity-0"
                }`}>
                  <div className="ml-5 pl-4 border-l border-neutral-200 dark:border-neutral-800 space-y-1 py-1">
                    {node.items.map(subItem => (
                      <button
                        key={subItem}
                        onClick={() => setActiveItem(subItem)}
                        className={`w-full flex items-center px-3 py-1.5 text-[13px] rounded-md transition-colors ${
                          activeItem === subItem
                            ? "text-blue-600 dark:text-blue-400 font-medium"
                            : "text-neutral-500 hover:text-neutral-900 dark:text-neutral-500 dark:hover:text-neutral-300"
                        }`}
                      >
                        {subItem}
                      </button>
                    ))}
                  </div>
                </div>
              </div>
            )
          }
        })}
      </div>
    </div>
  );
};

export default ExpandableNestedSidebar;

Elegant Collapsible Sidebar

import React, { useState } from "react";
import { LayoutDashboard, Users, Settings, ChevronRight, ChevronLeft, LogOut } from "lucide-react";

const CollapseSidebar = () => {
  const [isCollapsed, setIsCollapsed] = useState(false);
  const [activeItem, setActiveItem] = useState("Dashboard");

  const menuItems = [
    { name: "Dashboard", icon: LayoutDashboard },
    { name: "Users", icon: Users },
    { name: "Settings", icon: Settings },
  ];

  return (
    <div
      className={`flex flex-col bg-white dark:bg-[#0A0A0A] h-screen border-r border-neutral-200/60 dark:border-white/10 shadow-sm transition-all duration-300 ease-in-out ${
        isCollapsed ? "w-[80px]" : "w-[260px]"
      }`}
    >
      <div className="flex items-center justify-between p-6">
        <div className={`flex items-center gap-3 overflow-hidden transition-all duration-300 ${isCollapsed ? "w-0 opacity-0" : "w-auto opacity-100"}`}>
          <div className="w-8 h-8 bg-neutral-900 dark:bg-white rounded-lg min-w-[32px] flex items-center justify-center">
            <span className="text-white dark:text-neutral-900 font-bold">F</span>
          </div>
          <span className="font-semibold text-[18px] text-neutral-900 dark:text-white whitespace-nowrap">
            Fusion
          </span>
        </div>
        <button
          onClick={() => setIsCollapsed(!isCollapsed)}
          className="p-1.5 rounded-lg border border-neutral-200 dark:border-neutral-800 text-neutral-500 hover:bg-neutral-100 dark:hover:bg-neutral-900 transition-colors shadow-sm ml-auto"
        >
          {isCollapsed ? <ChevronRight size={16} /> : <ChevronLeft size={16} />}
        </button>
      </div>

      <div className="flex-1 overflow-y-auto px-4 py-4 space-y-2">
        {menuItems.map((item) => {
          const isActive = activeItem === item.name;
          return (
            <button
              key={item.name}
              onClick={() => setActiveItem(item.name)}
              className={`flex items-center rounded-xl transition-all duration-200 group relative ${
                isActive
                  ? "bg-neutral-100 dark:bg-neutral-900 text-neutral-900 dark:text-white"
                  : "text-neutral-500 hover:bg-neutral-50 dark:hover:bg-neutral-900/50 hover:text-neutral-800 dark:hover:text-neutral-300"
              } ${isCollapsed ? "p-3 justify-center" : "px-4 py-3 w-full"}`}
              title={isCollapsed ? item.name : undefined}
            >
              <item.icon className="w-5 h-5 min-w-[20px]" strokeWidth={isActive ? 2.5 : 2} />
              <span className={`text-[14px] font-medium ml-3 whitespace-nowrap overflow-hidden transition-all duration-300 ${
                isCollapsed ? "w-0 opacity-0 ml-0" : "w-auto opacity-100"
              }`}>
                {item.name}
              </span>
            </button>
          )
        })}
      </div>

      <div className="p-4 border-t border-neutral-200/60 dark:border-white/10">
        <button className={`flex items-center justify-center p-3 rounded-xl hover:bg-red-50 dark:hover:bg-red-500/10 text-red-500 dark:text-red-400 transition-colors w-full ${isCollapsed ? "" : "gap-3"}`}>
          <LogOut className="w-5 h-5 min-w-[20px]" />
          <span className={`text-[14px] font-medium whitespace-nowrap overflow-hidden transition-all duration-300 ${
            isCollapsed ? "w-0 opacity-0" : "w-auto opacity-100"
          }`}>
            Sign Out
          </span>
        </button>
      </div>
    </div>
  );
};

export default CollapseSidebar;