Shadcn Sidebar
The shadcn/ui Sidebar is a composable, collapsible application navigation panel, styled with Tailwind CSS v4. A provider manages open and collapsed state, and menu, group, and trigger parts assemble dashboard and admin layouts that adapt to mobile. Sidebars power app shells across ShadcnStore application blocks.
Key features
- A complete, composable app shell: provider, header, content, footer, menu, rail, inset, and trigger.
- Three desktop modes: icon collapse, off-canvas hide/show, and a fixed non-collapsible layout.
- Menu groups, active links, nested links, badges, hover actions, workspace menus, and account menus.
- Responsive Sheet behavior on mobile, plus
⌘Bon macOS /Ctrl+Bon Windows. - Controlled and uncontrolled state, sidebar-specific width and color tokens, and left/right placement.
Installation
npx shadcn@latest add sidebarUsage
Wrap the application shell in SidebarProvider. Keep the app sidebar and the page content as siblings, then use SidebarTrigger anywhere inside the provider.
import {
SidebarProvider,
Sidebar,
SidebarHeader,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarMenu,
SidebarMenuItem,
SidebarMenuButton,
SidebarFooter,
SidebarRail,
SidebarInset,
SidebarTrigger,
} from "@/components/ui/sidebar"
export function Layout() {
return (
<SidebarProvider>
<Sidebar>
<SidebarHeader>{/* workspace switcher or product identity */}</SidebarHeader>
<SidebarContent>
<SidebarGroup>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton>Home</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
<SidebarFooter>{/* account menu or settings */}</SidebarFooter>
<SidebarRail />
</Sidebar>
<SidebarInset>
<header>
<SidebarTrigger />
</header>
<main>{/* page content */}</main>
</SidebarInset>
</SidebarProvider>
)
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Composition
The component is intentionally made of small pieces. Start with this structure, then add only the parts your application needs.
SidebarProvider
├── Sidebar
│ ├── SidebarHeader
│ ├── SidebarContent
│ │ └── SidebarGroup
│ │ ├── SidebarGroupLabel
│ │ ├── SidebarGroupAction
│ │ └── SidebarMenu
│ │ └── SidebarMenuItem
│ │ ├── SidebarMenuButton
│ │ ├── SidebarMenuAction
│ │ ├── SidebarMenuBadge
│ │ └── SidebarMenuSub
│ ├── SidebarFooter
│ └── SidebarRail
├── SidebarInset
└── SidebarTrigger2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Collapsible modes
Use collapsible="icon" when users should retain quick access to navigation icons. Use offcanvas when the sidebar should disappear completely. Use none only for fixed layouts that are never meant to collapse.
<Sidebar collapsible="icon">...</Sidebar>
<Sidebar collapsible="offcanvas">...</Sidebar>
<Sidebar collapsible="none">...</Sidebar>2
3
The app-shell demo above uses icon collapse. Its trigger, rail, workspace menu, account menu, active item, badge, hover action, and nested navigation are all interactive.
Variants and placement
sidebar is the standard edge-to-edge layout. floating adds an inset, rounded sidebar panel. inset also expects the main content to be wrapped with SidebarInset.
<Sidebar variant="sidebar" />
<Sidebar variant="floating" />
<SidebarProvider>
<Sidebar variant="inset" />
<SidebarInset>{/* page content */}</SidebarInset>
</SidebarProvider>
<Sidebar side="right" />2
3
4
5
6
7
8
9
Navigation patterns
Use a real link for navigation, set isActive on the current destination, and use a nested menu when the hierarchy is already visible in the page structure.
<SidebarMenuItem>
<SidebarMenuButton render={<a href="/projects" />} isActive>
<FolderKanban />
<span>Projects</span>
</SidebarMenuButton>
<SidebarMenuBadge>12</SidebarMenuBadge>
<SidebarMenuAction showOnHover aria-label="Project actions">
<MoreHorizontal />
</SidebarMenuAction>
<SidebarMenuSub>
<SidebarMenuSubItem>
<SidebarMenuSubButton render={<a href="/projects/recent" />}>
Recent
</SidebarMenuSubButton>
</SidebarMenuSubItem>
</SidebarMenuSub>
</SidebarMenuItem>2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
For compact app shells, SidebarMenuButton accepts tooltip. The tooltip appears only when an icon sidebar is collapsed.
Provider state and keyboard shortcut
SidebarProvider manages uncontrolled state by default and writes the desktop preference to a cookie when it changes. Pass open and onOpenChange to make it controlled; read the cookie at your application boundary when you want to restore a preference after reload.
function AppShell() {
const [open, setOpen] = React.useState(true)
return (
<SidebarProvider open={open} onOpenChange={setOpen}>
<Sidebar />
<SidebarInset>
<SidebarTrigger />
</SidebarInset>
</SidebarProvider>
)
}2
3
4
5
6
7
8
9
10
11
12
Users can toggle the sidebar with ⌘B on macOS or Ctrl+B on Windows. useSidebar() exposes state, open, setOpen, openMobile, setOpenMobile, isMobile, and toggleSidebar for custom controls.
Responsive behavior
Below the desktop breakpoint, Sidebar renders as a slide-in Sheet. Keep a visible SidebarTrigger in the page header and ensure each menu destination can receive focus. The same provider automatically switches the trigger between desktop collapse and mobile Sheet state.
Props
| Component | Prop | Values | Default |
|---|---|---|---|
SidebarProvider | defaultOpen | boolean | true |
SidebarProvider | open / onOpenChange | controlled boolean state | — |
Sidebar | side | left / right | left |
Sidebar | variant | sidebar / floating / inset | sidebar |
Sidebar | collapsible | offcanvas / icon / none | offcanvas |
SidebarMenuButton | isActive | boolean | false |
SidebarMenuButton | tooltip | label or tooltip props | — |
Theming and width
Sidebar uses dedicated semantic tokens, so its surface can differ from the main application without hard-coded colors. Adjust a single sidebar’s width through provider style variables.
<SidebarProvider
style={
{
"--sidebar-width": "18rem",
"--sidebar-width-mobile": "20rem",
} as React.CSSProperties
}
>
<Sidebar />
</SidebarProvider>2
3
4
5
6
7
8
9
10
The sidebar color tokens are --sidebar, --sidebar-foreground, --sidebar-primary, --sidebar-accent, --sidebar-border, and --sidebar-ring.
Built on shadcn primitives
The Sidebar is composed from primitives shadcn already installs; its collapsing behavior is provided by SidebarProvider.
Accessibility
- Keep
SidebarTriggerreachable and visible in the application header. - Use anchors for destinations and buttons only for actions such as opening a menu or toggling a collapsible group.
- Mark the current destination with
isActive; in routed applications also provide the appropriate current-page semantics. - On mobile, the Sidebar becomes a dialog-style Sheet with focus handling. Test the open, close, and Escape paths on the final application.
- Give icon-only actions an accessible label and retain tooltips as supplementary—not sole—labels.
When to use the Sidebar
Use a Sidebar for primary navigation in dashboards, admin panels, and apps that need persistent, collapsible navigation. For a temporary side panel, use a Sheet; for adjustable split layouts, use Resizable panels.
Used in these blocks
- App shells: dashboard navigation.
- Apps: admin layouts.
- Datatables: navigation beside data.
Related components
The Sidebar uses Button-style menu items, a Separator between groups, and often a Dropdown Menu for the account menu. On mobile it behaves like a Sheet.
FAQ
What is the shadcn sidebar used for?
The Sidebar is a composable, collapsible application navigation panel with a provider, menu, groups, and a trigger, used to build dashboard and admin layouts.
How does the sidebar collapse?
SidebarProvider manages open state; SidebarTrigger toggles it, and the collapsible prop controls whether it collapses to icons, offcanvas, or stays fixed.
Does the sidebar work on mobile?
Yes. On small screens it renders as a slide-in sheet, and the trigger opens it.
How do I persist the collapsed state?
The provider writes the state to a sidebar_state cookie. Read that cookie at your application boundary and pass the result as defaultOpen, or manage open yourself with onOpenChange.