Navigation and layout
Sidebar
A responsive application sidebar with rails, panels, menus, and collapsible modes.
Install
npx shadcn@latest add https://4af.selfsimilar.dev/r/sidebar.jsonUsage
import {
Sidebar,
SidebarContent,
SidebarMenu,
SidebarMenuCollapsible,
SidebarMenuCollapsibleContent,
SidebarMenuCollapsibleTrigger,
SidebarProvider,
SidebarTrigger,
} from "@/components/ui/sidebar";
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarMenu>
<SidebarMenuCollapsible defaultOpen>
<SidebarMenuCollapsibleTrigger>Projects</SidebarMenuCollapsibleTrigger>
<SidebarMenuCollapsibleContent>Navigation</SidebarMenuCollapsibleContent>
</SidebarMenuCollapsible>
</SidebarMenu>
</SidebarContent>
</Sidebar>
<main><SidebarTrigger />Page content</main>
</SidebarProvider>API
Main exports: SidebarProvider, Sidebar, SidebarPanel, SidebarHeaderButton, and the
menu, group, submenu, action, badge, and skeleton parts
A responsive application sidebar.
variant:sidebar,floating,inset,split,split-floating, orsplit-inset.- Controlled or uncontrolled collapse, menu sections, nested rows, collapsible menu rows, badges, and loading skeletons.
- A full-width primary action in the header (
SidebarHeaderButton). - Split layouts pair
SidebarRailButtoncontrols, each with avalue, withSidebarPanelsections.activePanel,defaultActivePanel, andonActivePanelChangeselect the wide panel.
SidebarRailButton tooltip="Projects" labels a rail icon. Moving between rail icons opens their
tooltips immediately, and the entrance transition still plays.
With collapsible="offcanvas", collapsed navigation leaves the tab order and accessibility
tree once its exit finishes. If collapse happens while focus is inside, focus returns to the
external SidebarTrigger in the same provider, or the edge SidebarRail when present. Keep a
trigger outside the panel so keyboard users can reopen it. Icon and noncollapsing sidebars keep
their navigation available.
Menu control geometry
SidebarMenuButton supports size="sm", size="default", and size="lg". The compact
sm row uses a 6px radius; default and lg use an 8px radius. Nested
SidebarMenuSubButton rows use a 6px radius, and fixed split-rail buttons are 32px squares
with an 8px radius.
Collapsible menu sections
SidebarGroup provides visual grouping but does not own open state. For an expandable menu
row, use SidebarMenuCollapsible with SidebarMenuCollapsibleTrigger and
SidebarMenuCollapsibleContent:
<SidebarMenu>
<SidebarMenuCollapsible defaultOpen>
<SidebarMenuCollapsibleTrigger>
<Folder />
<span>Projects</span>
</SidebarMenuCollapsibleTrigger>
<SidebarMenuCollapsibleContent>
<SidebarMenuSub>
<SidebarMenuSubItem>
<SidebarMenuSubButton href="/projects/acme">Acme</SidebarMenuSubButton>
</SidebarMenuSubItem>
</SidebarMenuSub>
</SidebarMenuCollapsibleContent>
</SidebarMenuCollapsible>
</SidebarMenu>The trigger includes a trailing ChevronDown that points right while closed and down while
open. Pass chevron={false} when the trigger supplies its own indicator. A sibling
SidebarMenuAction sits just before the chevron, and a sibling SidebarMenuBadge takes its own
slot before both, so they never overlap. Hovering a nested row highlights only that row. The
collapsible root accepts Base UI's defaultOpen, open, onOpenChange, and disabled
props.
Header composition
A header contains one full-width SidebarHeaderButton, or two wrapped in SidebarHeaderRow:
<SidebarHeader>
<span>Emails</span>
<SidebarHeaderRow>
<SidebarHeaderButton><Plus />Compose</SidebarHeaderButton>
<SidebarHeaderButton variant="outline"><Search />Search</SidebarHeaderButton>
</SidebarHeaderRow>
</SidebarHeader>The row owns spacing, divides width evenly, and stacks its buttons when the sidebar collapses to
icons. Add className="flex-none" when a button should retain its own width. Compose menus with
Dropdown Menu rather than embedding a separate menu implementation in Sidebar.
Pinning the panel open
hideCollapseHandle removes the edge strip that toggles the panel. Use it when the panel is
pinned open (a controlled open that never changes), so there is no control that does
nothing.
<Sidebar variant="split-inset" collapsible="icon" hideCollapseHandle={pinned} rail={rail}>