Sidebar
A composable, themeable and customizable sidebar component. Created by Shadcn, animated by Animate UI, updated by malinskibeniamin.
Powered by
Installation
npx shadcn@latest add @redpanda/sidebarpnpm dlx shadcn@latest add @redpanda/sidebaryarn dlx shadcn@latest add @redpanda/sidebarbunx shadcn@latest add @redpanda/sidebarnubx shadcn@latest add @redpanda/sidebaraube dlx shadcn@latest add @redpanda/sidebarRequires React and ReactDOM 19.2+ for useEffectEvent.
The sidebar examples share a demo account menu with an explicit name, email, avatar and fallback initials. The trigger and popup show the same identity. Its account actions are placeholders: connect them to your application when adapting an example. Installing a sidebar demo includes the shared helper; the Sidebar component itself remains composable.
On mobile, a collapsible Sidebar owns an edge-to-edge navigation dialog with the same sidebar tokens as desktop. Escape and outside presses dismiss it and restore focus to its opener. A real Close sidebar action is available to assistive technology; keyboard focus reveals it as a visible control. The dialog uses the configured portal container, and native Sidebar refs and attributes reach its popup.
collapsible="none" remains inline at every viewport width; it does not become a mobile dialog. The right-side inspector example deliberately uses that contract.
Sidebar owns its rail, separator and navigation-hover recipes. SidebarSeparator supports decorative or semantic separators and orientation, but no longer inherits a generic Separator color variant that its sidebar-border treatment always overrode. Keep the contextual sidebar separator rather than recoloring it from a caller.
Actions, links and unavailable destinations
Use SidebarMenuButton for an action, SidebarMenuLink for a main navigation destination and SidebarMenuSubLink for a nested destination. Links own a native href, retain link semantics and support ordinary Enter, modifier-click and context-menu navigation. SidebarMenuSubButton was removed: its default element was an anchor, not an action button.
<SidebarMenuItem> <SidebarMenuLink href="/projects">Projects</SidebarMenuLink></SidebarMenuItem><SidebarMenuSubItem> <SidebarMenuSubLink aria-describedby="unavailable-feature-reason" disabled href="/knowledge" > Knowledge base </SidebarMenuSubLink> <span className="sr-only" id="unavailable-feature-reason"> Available after your administrator enables this feature. </span></SidebarMenuSubItem>Native actions use type="button" by default, including when a tooltip is present. Disabled actions cannot activate or submit an enclosing form. Disabled links retain aria-disabled link semantics, remove their navigable href, reject activation and leave the sequential Tab order. Keep the reason persistently associated with aria-describedby; a visual tooltip alone is not an accessible explanation. Use useId when repeated instances need unique description IDs.
Enabled controls still accept Base UI render composition, including a router link that forwards its native props and ref. Do not combine disabled with render. The type contract rejects it and JavaScript consumers receive a descriptive error. A custom renderer can replace navigation attributes or execute its own handlers before merged owner handlers; Sidebar cannot honestly guarantee its disabled behavior. When availability is conditional, render the disabled native action/link branch without render, and use the router-rendered branch only when enabled.
When to use
Sidebars provide persistent navigation and complementary content. Use this decision tree:
Usage
<SidebarProvider> <Sidebar> <SidebarHeader> <SidebarMenu> <SidebarMenuItem>Item 1</SidebarMenuItem> <SidebarMenuItem>Item 2</SidebarMenuItem> <SidebarMenuItem>Item 3</SidebarMenuItem> </SidebarMenu> </SidebarHeader> <SidebarContent> <SidebarGroup> <SidebarGroupLabel>Label 1</SidebarGroupLabel> <SidebarMenu> <SidebarMenuItem>Item 1</SidebarMenuItem> <SidebarMenuItem>Item 2</SidebarMenuItem> <SidebarMenuItem>Item 3</SidebarMenuItem> </SidebarMenu> </SidebarGroup> <SidebarGroup> <SidebarGroupLabel>Label 2</SidebarGroupLabel> <SidebarMenu> <SidebarMenuItem>Item 1</SidebarMenuItem> <SidebarMenuItem>Item 2</SidebarMenuItem> <SidebarMenuItem>Item 3</SidebarMenuItem> </SidebarMenu> </SidebarGroup> </SidebarContent> <SidebarFooter> <SidebarMenu> <SidebarMenuItem>Item 1</SidebarMenuItem> <SidebarMenuItem>Item 2</SidebarMenuItem> <SidebarMenuItem>Item 3</SidebarMenuItem> </SidebarMenu> </SidebarFooter> <SidebarRail /> </Sidebar> <SidebarInset> <SidebarTrigger /> {...} </SidebarInset></SidebarProvider>Props
Animate UI props
Sidebar
containerClassName?string
The class name of the sidebar container
stringanimateOnHover?boolean
Whether to animate the sidebar on hover
booleantruetransition?Transition
The transition of the sidebar
Transition{ type: "spring", stiffness: 350, damping: 35 }Examples
Loading skeleton
SidebarMenuSkeleton renders random per-row widths by default. Pass uniform for full-width rows that match evenly
sized nav items.
Wide content in the inset
SidebarInset sets min-w-0 so it can shrink below its content’s intrinsic width. Without it, a flex item’s
implicit min-width: auto lets one wide descendant — a long code line, a wide table — widen the whole shell and
scroll the document horizontally. The wide block still needs its own overflow-x-auto, as the pre here has: that
is what gives the overflow somewhere to go instead of spilling out of the inset.
With a fixed banner
Pass bannerHeight on SidebarProvider so the sidebar container and inset are offset below a fixed top banner. The
mobile dialog is intentionally not offset: it slides over the banner. This app-shell example uses a collapsible
Sidebar and SidebarInset; collapsible="none" stays inline and does not consume the fixed-container offset. The
example also uses SidebarMenuBadge variant="secondary" for emphasis badges next to nav items.
The application examples share their actual navigation catalogs and Cloud shell rather than copying menu markup. Navigation leaves are native links; only groups with children are disclosure buttons. The Cluster and Serverless examples expose the authored AI Agents children, including the unavailable Knowledge Base and its reason. Their # destinations are illustrative document-top links, not simulated backend routes. The Admin and Console integration branding is noninteractive; the billing examples retain their distinct expired-trial and remaining-balance features.
Cloud UI
Cloud UI (With Billing credits)
The billing examples use a small standard Card and a primary Upgrade action. The balance example keeps the remaining days and available credits visible. Collapsed sidebars provide a named review button that opens the same details and Upgrade action; mobile sidebars present those details in a drawer.
An example sidebar representation for Cloud UI with billing credits for a free trial.
Cloud UI (With Billing expired)
An example sidebar representation for Cloud UI with billing free trial expired.
Cloud UI (Cluster)
An example sidebar representation for Cloud UI within a cluster.
Cloud UI (Serverless)
An example sidebar representation for Cloud UI within a serverless cluster.
Console UI
Console UI (Self-hosted)
An example sidebar representation for self-hosted Console UI.
Admin UI
Credits
- We take our inspiration from Shadcn UI for the sidebar component and styling.
- We use Animate UI from imskyleen for all the animations.