shadcn Sidebar Generator
Configure it visually, copy the component and the provider shell.
Click the trigger to see the offcanvas collapse behaviour.
import { Calendar, Home, Inbox, Settings } from "lucide-react"
import {
Sidebar,
SidebarHeader,
SidebarContent,
SidebarGroup,
SidebarGroupLabel,
SidebarGroupContent,
SidebarMenu,
SidebarMenuItem,
SidebarMenuButton,
SidebarFooter,
SidebarProvider,
SidebarRail,
SidebarTrigger,
} from "@/components/ui/sidebar"
export function AppSidebar() {
return (
<Sidebar>
<SidebarHeader>
{/* brand or workspace switcher */}
</SidebarHeader>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Application</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton asChild>
<a href="#">
<Home />
<span>Home</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton asChild>
<a href="#">
<Inbox />
<span>Inbox</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton asChild>
<a href="#">
<Calendar />
<span>Calendar</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
<SidebarGroup>
<SidebarGroupLabel>Settings</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton asChild>
<a href="#">
<Settings />
<span>General</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
<SidebarFooter>
{/* user menu */}
</SidebarFooter>
<SidebarRail />
</Sidebar>
)
}
export function Layout({ children }: { children: React.ReactNode }) {
return (
<SidebarProvider>
<AppSidebar />
<main className="flex-1">
<SidebarTrigger />
{children}
</main>
</SidebarProvider>
)
}
The provider shell is the part that's usually missing
The shadcn sidebar has three props that change its shape entirely, and names — floating,
inset, offcanvas — that do not tell you much until you see them. This
renders a miniature app shell so each combination is visible, and gives you back both the
sidebar and the SidebarProvider layout it has to live inside.
How to use it
-
Choose the shape
Side, variant and collapse mode. The preview is a miniature app shell, so you can see what floating and inset actually do rather than guessing from the names.
-
Toggle the parts
Header, footer, rail and SidebarInset. Only the parts you enable appear in the imports and the markup.
-
Build the menu
Add groups and items with Lucide icons. These become SidebarGroup, SidebarMenu and SidebarMenuButton blocks.
-
Test the collapse
Click the trigger in the preview to watch offcanvas, icon and none behave differently.
-
Copy both pieces
You get AppSidebar and the layout shell that wraps it — the provider setup is the part most snippets leave out.
Three props do most of the work
side is left or right. variant decides whether the panel is flush
(sidebar), detached with its own border (floating), or leaves the
main content in a rounded card on the page background (inset).
collapsible decides what happens when it closes: slide away entirely
(offcanvas), shrink to an icon rail (icon), or never close at all
(none).
SidebarProvider has to be outermost
It owns the open state, the keyboard shortcut and the mobile sheet. A
SidebarTrigger rendered outside it silently does nothing, which is the single
most common thing that goes wrong. The output here always includes the shell so the two cannot
drift apart.
Persisting the open state
The component stores its state in a sidebar_state cookie. Read that cookie on the
server and pass it as defaultOpen, otherwise the sidebar renders open and snaps
shut once the client hydrates.
Laying out the page around it
Everything beside the sidebar is still an ordinary grid problem. For the content area — a dashboard, an app shell, a settings page — use the dashboard layout or the shadcn grid generator.
Frequently asked questions
How do I add a sidebar in shadcn/ui?
npx shadcn@latest add sidebar, then wrap your app in SidebarProvider with an <AppSidebar /> and your main content as siblings. The provider owns the open state and the mobile sheet, so nothing works until it is the outermost element.What is the difference between the sidebar, floating and inset variants?
sidebar is flush against the viewport edge, floating detaches it with a border and rounded corners, and inset pushes the main content into a rounded card so the sidebar sits on the page background. inset expects you to wrap the main area in SidebarInset.What does collapsible="icon" do?
offcanvas slides it fully off screen, and none makes it permanently open with no trigger. On mobile all variants become a sheet regardless of this setting.Why is my SidebarTrigger not doing anything?
SidebarProvider, so it has no context to toggle, or the sidebar is set to collapsible="none", which has no collapsed state to switch to.How do I put the shadcn sidebar on the right?
side="right" to <Sidebar>. Also swap the DOM order so the sidebar comes after the main content — keyboard users follow the DOM, not the visual position.How do I keep the sidebar state between page loads?
sidebar_state cookie. In Next.js, read it in a server component and pass the value to SidebarProvider as defaultOpen so the first render matches and the sidebar does not flash open.