Navigation
Sidebar
The primary navigation rail for an app — a workspace switcher and search up top, grouped menus with icons, expandable submenus and count badges in the middle, an account menu at the foot. Collapses to a 64px icon rail to reclaim space, with tooltips standing in for labels, and remembers its collapsed and expanded-group state across visits.
npx shadcn@latest add @orbit/sidebarOverview
A live sidebar inside an app frame. Click the panel icon (or the right edge) to collapse to icons, expand a menu group, or press ⌘/Ctrl+B while focus is in the rail. Collapsed and expanded-group state persist to localStorage.
Anatomy
A fixed header and footer bracket a scrolling content area. Each menu item is an icon, a label, and an optional badge or disclosure chevron; nested items sit indented on a hairline guide, each marked with a dot that tints when active. A parent whose child is selected keeps a tinted icon — the active trail — so you stay oriented even collapsed.
Collapsing
The whole rail animates between 264 and 64 pixels. Collapsed, labels give way to centered icons, group labels become dividers, badges shrink to dots, and hovering an icon reveals its label. Each instance below is independently live.
Composition
The sidebar is assembled from parts, so variants are compositions: leave out <SidebarFooter> for no footer, skip badge props to drop the pills, or pass defaultCollapsed to start as an icon rail. Every instance stays fully interactive.
Props
Navigation items render as any element you like — pass render={<Link href=…/>} and the item merges its styling, active state, and aria-current into your router link.
| Prop | Type | Default | Description |
|---|---|---|---|
| <Sidebar> collapsed | boolean | — | Controlled collapsed state; pair with onCollapsedChange. |
| <Sidebar> defaultCollapsed | boolean | false | Start as a 64px icon rail (uncontrolled). |
| <Sidebar> defaultOpenGroups | string[] | [] | Submenu ids that start expanded. |
| <Sidebar> collapsible | boolean | true | Set false for a fixed rail — no toggle, shortcut, or rail handle. |
| <Sidebar> storageKey | string | false | "sidebar" | localStorage namespace for `…-collapsed` and `…-expanded`; false disables persistence. |
| <SidebarMenuButton> icon | ReactNode | — | Leading 18×18 icon, drawn with currentColor so it follows the active tint. |
| <SidebarMenuButton> active | boolean | false | Current destination — brand-tinted row, sets aria-current="page". |
| <SidebarMenuButton> activeTrail | boolean | false | Parent of the active item: emphasized label, tinted icon, no fill. |
| <SidebarMenuButton> badge / badgeAccent | ReactNode / boolean | — | Count pill (accent = brand tint); collapses to a dot on the icon. |
| <SidebarMenuButton> tooltip | string | — | Collapsed hover-tooltip label; defaults to string children. |
| <SidebarMenuButton> render | ReactElement | — | Render as a custom element, e.g. render={<Link href=…/>}; props are merged. |
| <SidebarSubmenu> id | string | — | Stable id keying the group's expanded state and its persistence. |
| <SidebarSubmenuItem> active / render | boolean / ReactElement | — | Nested row with indent guide and dot; same render-prop contract. |
| Parts | components | — | SidebarHeader, SidebarContent, SidebarFooter, SidebarGroup(Label), SidebarMenu(Item), SidebarMenuBadge, SidebarSubmenuTrigger/Content, SidebarTrigger, SidebarRail, useSidebar(). |
Usage
Group by purpose
Three to seven items per labeled group. Long, flat lists are slow to scan and easy to lose your place in.
Nest more than two levels
A sidebar is for top-level navigation. Deep, arbitrary hierarchy belongs in a Tree or on a dedicated page.
Keep the active item obvious
One selected destination at a time, clearly tinted, so people always know where they are in the app.
Bury primary nav when collapsed
Collapse to icons to save space, but keep every destination one click or hover away — never inside a hidden menu.
Keyboard & accessibility
The content area is a semantic <nav>; items are real buttons or your own links, so Tab, Enter, and Space work natively. Active items set aria-current, submenu triggers set aria-expanded and aria-controls, closed submenus are inert so hidden links never take focus, and collapsed items keep their labels for screen readers.