Sidebar
Sidebar is a comprehensive navigation sidebar component with collapsible menus, submenus, mobile responsiveness, and multiple layout variants. It's built on a context provider and exposes a useSidebar hook for programmatic control.
Interactive example#
Sidebar · Live example
Use the embedded sidebar to switch sections or collapse it to an icon rail.
The code uses shared demo presentation helpers. Their complete source and styling are included in the LLM build context.
Import#
TSX
import {
SidebarProvider,
Sidebar,
SidebarContent,
SidebarHeader,
SidebarFooter,
SidebarGroup,
SidebarGroupLabel,
SidebarGroupContent,
SidebarMenu,
SidebarMenuItem,
SidebarMenuButton,
SidebarMenuBadge,
SidebarMenuSub,
SidebarMenuSubItem,
SidebarMenuSubButton,
SidebarTrigger,
SidebarInset,
SidebarSeparator,
useSidebar,
} from '@clidey/ux';
Setup#
Wrap your layout with SidebarProvider:
TSX
<SidebarProvider>
<AppSidebar />
<SidebarInset>
<main>{/* page content */}</main>
</SidebarInset>
</SidebarProvider>
Basic sidebar#
TSX
function AppSidebar() {
const navItems = [
{ title: 'Dashboard', icon: LayoutDashboard, href: '/' },
{ title: 'Projects', icon: FolderOpen, href: '/projects' },
{ title: 'Team', icon: Users, href: '/team' },
{ title: 'Settings', icon: Settings, href: '/settings' },
];
return (
<Sidebar>
<SidebarHeader>
<div className="px-2 py-1.5 font-semibold">My App</div>
</SidebarHeader>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Navigation</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{navItems.map((item) => (
<SidebarMenuItem key={item.title}>
<SidebarMenuButton>
<a href={item.href}>
<item.icon />
<span>{item.title}</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
<SidebarFooter>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton>
<a href="/logout">
<LogOut />
<span>Log out</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarFooter>
</Sidebar>
);
}
With sub-menus#
TSX
<SidebarMenuItem>
<SidebarMenuButton>
<FileText />
<span>Documents</span>
</SidebarMenuButton>
<SidebarMenuSub>
<SidebarMenuSubItem>
<SidebarMenuSubButton>
<a href="/docs/reports">Reports</a>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
<SidebarMenuSubItem>
<SidebarMenuSubButton>
<a href="/docs/invoices">Invoices</a>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
</SidebarMenuSub>
</SidebarMenuItem>
With badge#
TSX
<SidebarMenuButton>
<Bell />
<span>Notifications</span>
<SidebarMenuBadge>12</SidebarMenuBadge>
</SidebarMenuButton>
Sidebar variants#
TSX
{/* Default: full-width sidebar */}
<Sidebar variant="sidebar">
{/* Floating: detached with shadow */}
<Sidebar variant="floating">
{/* Inset: content is inset from edges */}
<Sidebar variant="inset">
Collapsible behavior#
TSX
{/* Slides off-canvas when collapsed (default) */}
<Sidebar collapsible="offcanvas">
{/* Collapses to icon-only mode */}
<Sidebar collapsible="icon">
{/* Never collapses */}
<Sidebar collapsible="none">
Toggle button#
Add SidebarTrigger to the page header to give users a collapse/expand button:
TSX
<header className="flex items-center gap-2 p-4 border-b">
<SidebarTrigger />
<h1>Page Title</h1>
</header>
useSidebar hook#
TSX
function SidebarControl() {
const { open, setOpen, toggleSidebar, isMobile, state } = useSidebar();
return (
<button onClick={toggleSidebar}>
{state === 'expanded' ? 'Collapse' : 'Expand'}
</button>
);
}
Hook return values
| Value | Type | Description |
|---|---|---|
state | "expanded" | "collapsed" | Current sidebar state. |
open | boolean | Whether the sidebar is open. |
setOpen | (open: boolean) => void | Programmatically open or close. |
isMobile | boolean | Whether the viewport is mobile-sized. |
openMobile | boolean | Mobile sheet open state. |
setOpenMobile | (open: boolean) => void | Control mobile sheet. |
toggleSidebar | () => void | Toggle between expanded and collapsed. |
SidebarProvider Props#
| Prop | Type | Default | Description |
|---|---|---|---|
defaultOpen | boolean | true | Initial open state. |
open | boolean | — | Controlled open state. |
onOpenChange | (open: boolean) => void | — | Called when open state changes. |
Sidebar Props#
| Prop | Type | Default | Description |
|---|---|---|---|
side | "left" | "right" | "left" | Which side the sidebar appears on. |
variant | "sidebar" | "floating" | "inset" | "embed" | "sidebar" | Visual style variant. |
collapsible | "offcanvas" | "icon" | "none" | "offcanvas" | Collapse behavior. |
SidebarMenuButton Props#
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "default" | "outline" | "default" | Visual style. |
size | "default" | "sm" | "lg" | "default" | Button size. |
isActive | boolean | false | Highlights the button as the current page. |
asChild | boolean | false | Render as the child element (e.g., <a>). |
tooltip | string | TooltipContent | — | Tooltip shown in icon-only collapsed mode. |
Was this page helpful?
