Switch between the Sidebar , Floating and Inset variants with the tabs in the demo. Collapse it to icons with the trigger or by clicking the rail. On a phone, the trigger opens it as a sheet.
Sidebars are one of the most complex components to build. They are central
to any application and often contain a lot of moving parts.
We now have a solid foundation to build on top of. Composable. Themeable.
Customizable.
Browse the Blocks Library .
app/layout.tsxCopy import { SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar"
import { AppSidebar } from "@/components/app-sidebar"
export default function Layout ({ children } : { children : React . ReactNode }) {
return (
< SidebarProvider >
< AppSidebar />
< main >
< SidebarTrigger />
{ children }
</ main >
</ SidebarProvider >
)
}
components/app-sidebar.tsxCopy import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarGroup,
SidebarHeader,
} from "@/components/ui/sidebar"
export function AppSidebar () {
return (
< Sidebar >
< SidebarHeader />
< SidebarContent >
< SidebarGroup />
< SidebarGroup />
</ SidebarContent >
< SidebarFooter />
</ Sidebar >
)
}
Use the following composition to build a Sidebar layout:
Copy SidebarProvider
├── Sidebar
│ ├── SidebarHeader
│ ├── SidebarContent
│ │ ├── SidebarGroup
│ │ │ ├── SidebarGroupLabel
│ │ │ ├── SidebarGroupAction
│ │ │ ├── SidebarGroupContent
│ │ │ └── SidebarMenu
│ │ │ ├── SidebarMenuItem
│ │ │ │ ├── SidebarMenuButton
│ │ │ │ ├── SidebarMenuAction
│ │ │ │ └── SidebarMenuBadge
│ │ │ └── SidebarMenuItem
│ │ │ ├── SidebarMenuButton
│ │ │ └── SidebarMenuSub
│ │ │ ├── SidebarMenuSubItem
│ │ │ └── SidebarMenuSubItem
│ │ └── SidebarGroup
│ │ └── SidebarMenu
│ │ ├── SidebarMenuItem
│ │ └── SidebarMenuItem
│ ├── SidebarFooter
│ └── SidebarRail
├── SidebarInset
└── SidebarTrigger
SidebarProvider : Handles collapsible state and provides sidebar context to child components.
Sidebar : The main collapsible sidebar panel.
SidebarHeader : Sticky at the top; use for branding, titles, or workspace switchers.
SidebarFooter : Sticky at the bottom; use for user menus, settings, or actions.
SidebarContent : Scrollable region between the header and footer.
SidebarGroup : Groups related navigation with optional label, action, and content areas.
SidebarMenu / SidebarMenuItem : Menu structure for links, badges, actions, and nested submenus.
SidebarRail : Resize handle for adjusting sidebar width when applicable.
SidebarInset : Wraps main content when using the inset variant.
SidebarTrigger : Control that toggles the sidebar open or collapsed.
The SidebarProvider component is used to provide the sidebar context to the Sidebar component. You should always wrap your application in a SidebarProvider component.
If you have a single sidebar in your application, you can use the SIDEBAR_WIDTH and SIDEBAR_WIDTH_MOBILE variables in sidebar.tsx to set the width of the sidebar.
components/ui/sidebar.tsxCopy const SIDEBAR_WIDTH = "16rem"
const SIDEBAR_WIDTH_MOBILE = "18rem"
For multiple sidebars in your application, you can use the --sidebar-width and --sidebar-width-mobile CSS variables in the style prop.
Copy < SidebarProvider
style ={
{
"--sidebar-width" : "20rem" ,
"--sidebar-width-mobile" : "20rem" ,
} as React . CSSProperties
}
>
< Sidebar />
</ SidebarProvider >
To trigger the sidebar, you use the cmd+b keyboard shortcut on Mac and ctrl+b on Windows.
components/ui/sidebar.tsxCopy const SIDEBAR_KEYBOARD_SHORTCUT = "b"
The main Sidebar component used to render a collapsible sidebar.
Note: If you use the inset variant, remember to wrap your main content
in a SidebarInset component.
Copy < SidebarProvider >
< Sidebar variant = "inset" />
< SidebarInset >
< main > { children } </ main >
</ SidebarInset >
</ SidebarProvider >
The useSidebar hook is used to control the sidebar.
Copy import { useSidebar } from "@/components/ui/sidebar"
export function AppSidebar () {
const {
state ,
open ,
setOpen ,
openMobile ,
setOpenMobile ,
isMobile ,
toggleSidebar ,
} = useSidebar ()
}
Use the SidebarHeader component to add a sticky header to the sidebar.
components/app-sidebar.tsxCopy < Sidebar >
< SidebarHeader >
< SidebarMenu >
< SidebarMenuItem >
< DropdownMenuTrigger >
< SidebarMenuButton >
Select Workspace
< ChevronDown className = "ml-auto" />
</ SidebarMenuButton >
< DropdownMenu className = "w-[--trigger-width]" >
< DropdownMenuItem >
< span > Acme Inc </ span >
</ DropdownMenuItem >
</ DropdownMenu >
</ DropdownMenuTrigger >
</ SidebarMenuItem >
</ SidebarMenu >
</ SidebarHeader >
</ Sidebar >
Use the SidebarFooter component to add a sticky footer to the sidebar.
Copy < Sidebar >
< SidebarFooter >
< SidebarMenu >
< SidebarMenuItem >
< SidebarMenuButton >
< User2 /> Username
</ SidebarMenuButton >
</ SidebarMenuItem >
</ SidebarMenu >
</ SidebarFooter >
</ Sidebar >
The SidebarContent component is used to wrap the content of the sidebar. This is where you add your SidebarGroup components. It is scrollable.
Copy < Sidebar >
< SidebarContent >
< SidebarGroup />
< SidebarGroup />
</ SidebarContent >
</ Sidebar >
Use the SidebarGroup component to create a section within the sidebar.
A SidebarGroup has a SidebarGroupLabel, a SidebarGroupContent and an optional SidebarGroupAction.
Copy < SidebarGroup >
< SidebarGroupLabel > Application </ SidebarGroupLabel >
< SidebarGroupAction >
< Plus /> < span className = "sr-only" > Add Project </ span >
</ SidebarGroupAction >
< SidebarGroupContent ></ SidebarGroupContent >
</ SidebarGroup >
To make a SidebarGroup collapsible, wrap it in a Collapsible.
Copy < Collapsible defaultExpanded className = "group/collapsible" >
< SidebarGroup >
< SidebarGroupLabel elementType ={ CollapsibleTrigger } >
Help
< ChevronDown className = "ml-auto transition-transform group-data-expanded/collapsible:rotate-180" />
</ SidebarGroupLabel >
< CollapsibleContent >
< SidebarGroupContent />
</ CollapsibleContent >
</ SidebarGroup >
</ Collapsible >
The SidebarMenu component is used for building a menu within a SidebarGroup.
Copy < SidebarMenu >
{ projects. map (( project ) => (
< SidebarMenuItem key ={ project.name } >
< SidebarMenuButton href ={ project.url } >
< project.icon />
< span > { project.name } </ span >
</ SidebarMenuButton >
</ SidebarMenuItem >
)) }
</ SidebarMenu >
The SidebarMenuButton component is used to render a menu button within a SidebarMenuItem.
By default, the SidebarMenuButton renders a button, but passing an href prop renders it as a link instead.
Use the isActive prop to mark a menu item as active.
Copy < SidebarMenuButton href = "#" isActive >
Home
</ SidebarMenuButton >
The SidebarMenuAction component is used to render a menu action within a SidebarMenuItem.
Copy < SidebarMenuItem >
< SidebarMenuButton href = "#" >
< Home />
< span > Home </ span >
</ SidebarMenuButton >
< SidebarMenuAction >
< Plus /> < span className = "sr-only" > Add Project </ span >
</ SidebarMenuAction >
</ SidebarMenuItem >
The SidebarMenuSub component is used to render a submenu within a SidebarMenu.
Copy < SidebarMenuItem >
< SidebarMenuButton />
< SidebarMenuSub >
< SidebarMenuSubItem >
< SidebarMenuSubButton />
</ SidebarMenuSubItem >
</ SidebarMenuSub >
</ SidebarMenuItem >
The SidebarMenuBadge component is used to render a badge within a SidebarMenuItem.
Copy < SidebarMenuItem >
< SidebarMenuButton />
< SidebarMenuBadge > 24 </ SidebarMenuBadge >
</ SidebarMenuItem >
The SidebarMenuSkeleton component is used to render a skeleton for a SidebarMenu.
Copy < SidebarMenu >
{ Array. from ({ length: 5 }). map (( _ , index ) => (
< SidebarMenuItem key ={ index } >
< SidebarMenuSkeleton />
</ SidebarMenuItem >
)) }
</ SidebarMenu >
Use the SidebarTrigger component to render a button that toggles the sidebar.
Copy import { useSidebar } from "@/components/ui/sidebar"
export function CustomTrigger () {
const { toggleSidebar } = useSidebar ()
return < button onClick ={ toggleSidebar } > Toggle Sidebar </ button >
}
The SidebarRail component is used to render a rail within a Sidebar. This rail can be used to toggle the sidebar.
Copy < Sidebar >
< SidebarHeader />
< SidebarContent >
< SidebarGroup />
</ SidebarContent >
< SidebarFooter />
< SidebarRail />
</ Sidebar >
Use the open and onOpenChange props to control the sidebar.
Copy export function AppSidebar () {
const [ open , setOpen ] = React. useState ( false )
return (
< SidebarProvider open ={ open } onOpenChange ={ setOpen } >
< Sidebar />
</ SidebarProvider >
)
}
We use the following CSS variables to theme the sidebar.
Copy @layer base {
:root {
--sidebar-background : 0 0 % 98 % ;
--sidebar-foreground : 240 5.3 % 26.1 % ;
--sidebar-primary : 240 5.9 % 10 % ;
--sidebar-primary-foreground : 0 0 % 98 % ;
--sidebar-accent : 240 4.8 % 95.9 % ;
--sidebar-accent-foreground : 240 5.9 % 10 % ;
--sidebar-border : 220 13 % 91 % ;
--sidebar-ring : 217.2 91.2 % 59.8 % ;
}
.dark {
--sidebar-background : 240 5.9 % 10 % ;
--sidebar-foreground : 240 4.8 % 95.9 % ;
--sidebar-primary : 0 0 % 98 % ;
--sidebar-primary-foreground : 240 5.9 % 10 % ;
--sidebar-accent : 240 3.7 % 15.9 % ;
--sidebar-accent-foreground : 240 4.8 % 95.9 % ;
--sidebar-border : 240 3.7 % 15.9 % ;
--sidebar-ring : 217.2 91.2 % 59.8 % ;
}
}
Here are some tips for styling the sidebar based on different states.
Copy < Sidebar collapsible = "icon" >
< SidebarContent >
< SidebarGroup className = "group-data-[collapsible=icon]:hidden" />
</ SidebarContent >
</ Sidebar >
Copy < SidebarMenuItem >
< SidebarMenuButton />
< SidebarMenuAction className = "peer-data-[active=true]/menu-button:opacity-100" />
</ SidebarMenuItem >
To enable RTL support, see the RTL configuration guide .
View RTL Sidebar