Components
Previous

Sidebar

A clean, modern sidebar with expanded and collapsed states, sub-menus, and active states.

Loading...
"use client";
 
import * as React from "react";
import {
  Home01Icon,
  PackageIcon,
  CreditCardIcon,
  UserMultiple02Icon,
  FolderIcon,
  Notification03Icon,
  HelpCircleIcon,
  Settings02Icon,
  ArrowRight01Icon,
  ArrowLeft01Icon,
} from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
 
import {
  Sidebar,
  SidebarContent,
  SidebarFooter,
  SidebarGroup,
  SidebarHeader,
  SidebarItem,
  SidebarProfile,
  SidebarSearch,
  SidebarSeparator,
  SidebarSubItem,
} from "@/components/sidebar";
 
export default function SidebarDemo() {
  const [expanded, setExpanded] = React.useState(true);
  const [paymentsExpanded, setPaymentsExpanded] = React.useState(true);
  const [activeItem, setActiveItem] = React.useState("Home");
 
  return (
    <div className="flex h-[600px] w-full items-center justify-center bg-background p-4">
      <div className="flex h-full overflow-hidden rounded-2xl border border-sidebar-border shadow-xl">
        <Sidebar expanded={expanded} onExpandedChange={setExpanded}>
          <SidebarHeader>
            <SidebarProfile
              name="Thomas Brown"
              email="thomas@riverstone.com"
              avatar="https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=80&h=80&fit=crop"
            />
          </SidebarHeader>
 
          <SidebarSearch />
 
          <SidebarContent>
            <SidebarGroup>
              <SidebarItem
                icon={Home01Icon}
                label="Home"
                active={activeItem === "Home"}
                onClick={() => setActiveItem("Home")}
              />
              <SidebarItem
                icon={PackageIcon}
                label="Products"
                active={activeItem === "Products"}
                onClick={() => setActiveItem("Products")}
              />
              <SidebarItem
                icon={CreditCardIcon}
                label="Payments"
                active={activeItem === "Payments"}
                hasChildren
                expanded={paymentsExpanded}
                onClick={() => setPaymentsExpanded(!paymentsExpanded)}
              >
                <SidebarSubItem
                  label="Pay"
                  active={activeItem === "Pay"}
                  onClick={() => setActiveItem("Pay")}
                />
                <SidebarSubItem
                  label="Get paid"
                  active={activeItem === "Get paid"}
                  onClick={() => setActiveItem("Get paid")}
                />
              </SidebarItem>
              <SidebarItem
                icon={UserMultiple02Icon}
                label="Customers"
                active={activeItem === "Customers"}
                onClick={() => setActiveItem("Customers")}
              />
            </SidebarGroup>
 
            <SidebarSeparator />
 
            <SidebarGroup>
              <SidebarItem
                icon={FolderIcon}
                label="Resources"
                active={activeItem === "Resources"}
                onClick={() => setActiveItem("Resources")}
              />
              <SidebarItem
                icon={Notification03Icon}
                label="Notifications"
                badge={5}
                active={activeItem === "Notifications"}
                onClick={() => setActiveItem("Notifications")}
              />
            </SidebarGroup>
 
            <SidebarSeparator />
 
            <SidebarGroup>
              <SidebarItem
                icon={HelpCircleIcon}
                label="Support"
                active={activeItem === "Support"}
                onClick={() => setActiveItem("Support")}
              />
              <SidebarItem
                icon={Settings02Icon}
                label="Settings"
                active={activeItem === "Settings"}
                onClick={() => setActiveItem("Settings")}
              />
            </SidebarGroup>
          </SidebarContent>
 
          <SidebarFooter className="px-4 pb-4">
            <button
              onClick={() => setExpanded(!expanded)}
              className="flex items-center gap-2 text-xs font-medium text-sidebar-foreground/50 hover:text-sidebar-foreground transition-colors"
            >
              <div className="flex size-6 items-center justify-center rounded-md border border-sidebar-border bg-sidebar shadow-sm group-hover:bg-sidebar-accent">
                <HugeiconsIcon
                  icon={expanded ? ArrowLeft01Icon : ArrowRight01Icon}
                  size={14}
                />
              </div>
              {expanded && <span>Collapse</span>}
            </button>
          </SidebarFooter>
        </Sidebar>
      </div>
    </div>
  );
}

Installation

bunx --bun shadcn@latest add "https://quatadahnasdami.xyz/r/sidebar.json"

Usage

import {
  Sidebar,
  SidebarContent,
  SidebarHeader,
  SidebarItem,
  SidebarProfile,
  SidebarSearch,
} from "@/components/sidebar";
export default function Layout({ children }) {
  return (
    <div className="flex h-screen overflow-hidden">
      <Sidebar>
        <SidebarHeader>
          <SidebarProfile
            name="Thomas Brown"
            email="thomas@riverstone.com"
            avatar="/avatar.png"
          />
        </SidebarHeader>
        <SidebarSearch />
        <SidebarContent>
          <SidebarItem icon={Home01Icon} label="Home" active />
          <SidebarItem icon={PackageIcon} label="Products" />
        </SidebarContent>
      </Sidebar>
      <main className="flex-1 overflow-auto">{children}</main>
    </div>
  );
}

Collapsed State

The sidebar supports a collapsed state that shows only icons and a red dot for notifications.

const [expanded, setExpanded] = useState(true);
 
<Sidebar expanded={expanded} onExpandedChange={setExpanded}>
  {/* ... */}
</Sidebar>

You can add sub-items to a sidebar item by passing hasChildren and rendering children.

const [paymentsExpanded, setPaymentsExpanded] = useState(false);
 
<SidebarItem
  icon={CreditCardIcon}
  label="Payments"
  hasChildren
  expanded={paymentsExpanded}
  onClick={() => setPaymentsExpanded(!paymentsExpanded)}
>
  <SidebarSubItem label="Pay" />
  <SidebarSubItem label="Get paid" />
</SidebarItem>

API Reference

PropTypeDefaultDescription
defaultExpandedbooleantrueInitial expanded state.
expandedboolean-Controlled expanded state.
onExpandedChangefunction-Called when expanded state changes.

SidebarItem

PropTypeDefaultDescription
iconIconType-Hugeicons icon component.
labelstring-Item label text.
activebooleanfalseWhether the item is active.
badgestring | number-Notification badge value.
hasChildrenbooleanfalseWhether the item has sub-items.
expandedbooleanfalseWhether the sub-menu is expanded.
onClickfunction-Click handler.