Sidebar
App-shell sidebar with collapsible width, context-driven open state, and composable Header/Content/Footer/Item parts. Provider-based so any descendant can toggle it.
Click the toggle to collapse or expand the sidebar.
Installation
pnpm dlx @hex-core/cli add sidebarAPI Reference
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | — | Controlled open state — read from SidebarProvider |
defaultOpen | boolean | true | Initial open state (uncontrolled) |
onOpenChange | function | — | Callback when open state flips: (open: boolean) => void |
side | string | left | Which edge the sidebar sits on: 'left' | 'right' |
AI Guidance
When to use
Use for persistent app-shell navigation: admin dashboards, document editors, SaaS sidebars. The Provider pattern lets any descendant component toggle the sidebar (e.g. a topbar button on mobile).
When not to use
Don't use for mobile-first UX (use Sheet — sidebar collapses to zero-width but Sheet gives a native drawer feel). Don't use for marketing sites (no shell). Don't use for contextual menus (use DropdownMenu or NavigationMenu).
Common mistakes
- Rendering Sidebar outside SidebarProvider — useSidebar throws
- Forgetting that SidebarProvider is a flex container — main content must be its direct sibling
- Using the wrong ordering for side='right' — SidebarProvider handles this via order-last
- Overriding the width variant manually instead of toggling open state
Accessibility
Sidebar is an <aside> landmark (not a modal — no focus trap). When collapsed, the aside sets inert + aria-hidden so its children are removed from the tab order and the accessibility tree. SidebarTrigger exposes aria-expanded and a rotating aria-label (suppressed when asChild so the consumer's visible label/aria-label wins). SidebarItem uses aria-current='page' when active. Focus rings use the ring token.
Related components
Token budget: 900