Sidebar
A composable, themeable and customizable sidebar component.
Usage
import { ChevronDown, ChevronRight, Folder, FileText, Users, Mail, Bell } from "lucide-react"
import { useState } from "react"
const collapsibleItems = [
{
title: "Documents",
icon: Folder,
items: [
{ title: "Reports", url: "#", icon: FileText },
{ title: "Invoices", url: "#", icon: FileText },
{ title: "Contracts", url: "#", icon: FileText },
],
},
{
title: "Team",
icon: Users,
items: [
{ title: "Members", url: "#", icon: Users },
{ title: "Roles", url: "#", icon: Users },
{ title: "Permissions", url: "#", icon: Users },
],
},
{
title: "Communication",
icon: Mail,
items: [
{ title: "Messages", url: "#", icon: Mail },
{ title: "Notifications", url: "#", icon: Bell },
{ title: "Announcements", url: "#", icon: Bell },
],
},
]
function CollapsibleMenuItem({ item }) {
const [isOpen, setIsOpen] = useState(false)
return (
<>
<SidebarMenuItem>
<SidebarMenuButton onClick={() => setIsOpen(!isOpen)} className="pl-lg">
<item.icon />
<span>{item.title}</span>
{isOpen ? <ChevronDown className="ml-auto" /> : <ChevronRight className="ml-auto" />}
</SidebarMenuButton>
{isOpen && (
<SidebarMenuSub>
{item.items.map((subItem) => (
<SidebarMenuSubItem key={subItem.title}>
<SidebarMenuSubButton asChild>
<a href={subItem.url}>
<subItem.icon />
<span>{subItem.title}</span>
</a>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
))}
</SidebarMenuSub>
)}
</SidebarMenuItem>
<SidebarSeparator />
</>
)
}
<SidebarProvider>
<Sidebar collapsible="offcanvas" className="relative">
<SidebarHeader>
<DropdownMenu className="w-full">
<DropdownMenuTrigger asChild>
<div className="flex items-center gap-md">
<Avatar>
<AvatarImage
src="https://github.com/shadcn.png"
alt="Team Avatar"
/>
<AvatarFallback>GT</AvatarFallback>
</Avatar>
<div className="flex items-center gap-sm">
Ge's Team
<ChevronDown size={16} />
</div>
</div>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-[var(--radix-dropdown-menu-trigger-width)]">
<DropdownMenuItem>
<span>Menu item1</span>
</DropdownMenuItem>
<DropdownMenuItem>
<span>Menu item2</span>
</DropdownMenuItem>
<DropdownMenuItem>
<span>Menu item3</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarHeader>
<SidebarContent>
<SidebarGroup>
<SidebarInput placeholder="Search for anything" />
<SidebarGroupContent>
<SidebarMenu>
{collapsibleItems.map((item) => (
<CollapsibleMenuItem key={item.title} item={item} />
))}
<SidebarMenuItem>
<SidebarMenuSubButton asChild>
<div>SidebarMenuAction</div>
</SidebarMenuSubButton>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<SidebarMenuAction>
<MoreHorizontal />
</SidebarMenuAction>
</DropdownMenuTrigger>
<DropdownMenuContent side="right" align="start">
<DropdownMenuItem>
<span>Edit Project</span>
</DropdownMenuItem>
<DropdownMenuItem>
<span>Delete Project</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
<SidebarMenuItem className="group-data-[collapsible=icon]:hidden">
<SidebarMenuSubButton>
<div>SidebarMenuBadge</div>
</SidebarMenuSubButton>
<SidebarMenuBadge>24</SidebarMenuBadge>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
<SidebarRail />
</Sidebar>
<SidebarTrigger />
</SidebarProvider>