Sidebar
A composable layout component for navigation screens, with responsive behavior and mobile menu support.
Installation
npx vayu-ui-cli@latest add sidebarUsage
Dashboard
<SidebarProvider>
<Sidebar>
<SidebarHeader>
<h2>Acme Inc</h2>
<MobileMenuButton />
</SidebarHeader>
<SidebarContent>
<SidebarMenu>
<SidebarMenuGroup label="Application">
<SidebarMenuItem href="/dashboard" active badge="3">
Dashboard
</SidebarMenuItem>
<SidebarMenuItem href="/analytics">Analytics</SidebarMenuItem>
</SidebarMenuGroup>
</SidebarMenu>
</SidebarContent>
<SidebarFooter>
<SidebarToggle floating />
</SidebarFooter>
</Sidebar>
</SidebarProvider>Anatomy
<SidebarProvider>
<Sidebar>
<SidebarHeader>
<MobileMenuButton />
</SidebarHeader>
<SidebarContent>
<SidebarMenu>
<SidebarMenuGroup label="...">
<SidebarMenuItem icon={<Icon />} badge="..." href="...">
Item Name
</SidebarMenuItem>
</SidebarMenuGroup>
</SidebarMenu>
</SidebarContent>
<SidebarFooter>
<SidebarToggle floating />
</SidebarFooter>
</Sidebar>
</SidebarProvider>Dashboard Shell Layout
The sidebar must live inside a locked-height shell so its internal scrolling works correctly.
<div className="h-screen overflow-hidden flex bg-canvas">
<SidebarProvider>
<MobileMenuButton />
<Sidebar>...</Sidebar>
<main className="flex-1 overflow-y-auto p-6">...</main>
</SidebarProvider>
</div>Why this matters: Sidebar uses h-screen and SidebarContent uses overflow-y-auto. If the outer wrapper stretches with content (min-h-screen without overflow-hidden), the sidebar grows with the page and the internal scrollbar never engages — the entire page scrolls instead.
Rail-Aware Header and Footer
SidebarHeader and SidebarFooter accept a function as children so you can render different content when the sidebar is collapsed to its 80px rail:
<SidebarHeader>
{({ collapsed, mobile }) =>
collapsed && !mobile ? (
<div className="flex justify-center">
<LogoIcon />
</div>
) : (
<div className="flex items-center gap-3">
<LogoIcon />
<span className="font-bold">App Name</span>
</div>
)
}
</SidebarHeader>Static children still work unchanged — this is purely opt-in.
Accessibility
- Keyboard support:
Escapekey dismisses mobile drawer, tab order strictly maintained visually. - ARIA attributes: Includes navigation landmarks (
aria-label),aria-hiddenoverlays, and correct semantic lists. - Focus behavior: Implements a focus trap within the mobile overlay to ensure screen readers don't escape.
Screen reader behavior
Screen readers announce the container as a "Main navigation" landmark. The sidebar dynamically skips from accessibility trees when fully collapsed or hidden on smaller viewpoints to avoid irrelevant noise.
Component Folder Structure
Sidebar/
├── Sidebar.tsx
├── SidebarContent.tsx
├── SidebarFooter.tsx
├── SidebarHeader.tsx
├── SidebarMenu.tsx
├── SidebarMenuItem.tsx
├── SidebarMobileMenuButton.tsx
├── SidebarToggle.tsx
├── hooks.ts
├── index.ts
└── types.tsProps
SidebarToggle
| Prop | Type | Default | Description |
|---|---|---|---|
floating | boolean | true | true = absolute floating handle on the sidebar edge. false = plain inline button. |
SidebarHeader
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | ((state: { collapsed, mobile }) => ReactNode) | — | Header content. Pass a function to react to rail state. |
SidebarFooter
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | ((state: { collapsed, mobile }) => ReactNode) | — | Footer content. Pass a function to react to rail state. |
SidebarMenuItem
| Prop | Type | Default | Description |
|---|---|---|---|
icon | ReactNode | - | Visual element placed to the left of the item text. |
active | boolean | false | Marks the item as the current active route. |
badge | string | number | - | Notice or counter displayed at the right edge. |
href | string | - | Hyperlink target destination. |
subItems | SubItem[] | - | Array of nested children { label, active, href } to render a dropdown. |
SidebarMenuGroup
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | - | Heading label for the grouping section. |