Layouts
Sidebar A collapsible panel for navigation or additional content, typically positioned on the side of the screen.
Basic
The sidebar is a versatile component designed to organize your site's content and navigation. It offers a structured overview of your site's layout, making it easier for users to explore and locate information.
Installation
If you hit any issues, make sure you check out the installation guide here for more information.
Composed components
When you install this component via the CLI, it automatically loads all composed components, so you don’t need to add them individually.
The Sidebar comes packed with several components to enhance functionality and provide a seamless experience.
Button Buttons play a crucial role in functionality, whether for submitting a form or navigating to another page.
Sheet A slide-in panel for presenting additional content without disrupting the main screen.
Tooltip A brief, informative message that appears when hovering or focusing on an element.
Badge A small, attention-grabbing UI element used to display notifications, status indicators, or counts in a compact format.
Manual installation
Make sure you also install the composed components and the required packages for the component to function properly.
Anatomy
Copy Copied import {
IconArchiveFill,
IconArrowDownFill,
IconArrowUpFill,
IconBrandIntentui,
IconBuildingFill,
IconChevronsY,
IconCircleCheckFill,
IconCircleQuestionmarkFill,
IconClockFill,
IconCommandRegular,
IconCreditCardFill,
IconCube,
IconDashboard,
IconDashboardFill,
IconDotsHorizontal,
IconHashtagFill,
IconHeadphonesFill,
IconListBulletsFill,
IconLogout,
IconMessageFill,
IconNotesFill,
IconPackageFill,
IconPlus,
IconSettings,
IconSettingsFill,
IconShieldFill,
IconShoppingBagFill,
IconTicketFill,
} from "@intentui/icons"
import { Avatar } from "@/components/ui/avatar"
import { Breadcrumbs } from "@/components/ui/breadcrumbs"
import { Link } from "@/components/ui/link"
import {
Menu,
MenuContent,
MenuHeader,
MenuItem,
MenuLabel,
MenuSection,
MenuSeparator,
MenuTrigger,
} from "@/components/ui/menu"
import {
Sidebar,
SidebarContent,
SidebarDisclosure,
SidebarDisclosureGroup,
SidebarDisclosurePanel,
SidebarDisclosureTrigger,
SidebarFooter,
SidebarHeader,
SidebarInset,
SidebarItem,
SidebarLabel,
SidebarLink,
SidebarNav,
SidebarProvider,
SidebarRail,
SidebarSection,
SidebarSectionGroup,
SidebarTrigger,
} from "@/components/ui/sidebar"
Copy Copied < SidebarProvider >
< Sidebar >
< SidebarHeader >
< Link href = "/docs/components/layouts/sidebar" className = "flex items-center gap-x-2" >
< IconBrandIntentui className = "size-8" />
< SidebarLabel className = "font-medium" >
Intent < span className = "text-muted-fg" >UI</ span >
</ SidebarLabel >
</ Link >
</ SidebarHeader >
< SidebarContent >
< SidebarSectionGroup >
< SidebarSection label = "Overview" >
< SidebarItem tooltip = "Overview" isCurrent href = "#" >
< IconDashboardFill />
< SidebarLabel >Overview</ SidebarLabel >
</ SidebarItem >
< SidebarItem tooltip = "Orders" >
{({ isCollapsed , isFocused }) => (
<>
< SidebarLink href = "#" >
< IconShoppingBagFill />
< SidebarLabel >Orders</ SidebarLabel >
</ SidebarLink >
{( ! isCollapsed || isFocused) && (
< Menu >
< MenuTrigger data-slot = "menu-action-trigger" aria-label = "Manage" >
< IconDotsHorizontal />
</ MenuTrigger >
< MenuContent popover = {{ offset: 0 , placement: "right top" }}>
< MenuItem href = "#new-order" >
< IconPlus />
Create New Order
</ MenuItem >
< MenuItem href = "#view-all" >
< IconListBulletsFill />
View All Orders
</ MenuItem >
< MenuItem href = "#pending-orders" >
< IconClockFill />
Pending Orders
</ MenuItem >
< MenuItem href = "#completed-orders" >
< IconCircleCheckFill />
Completed Orders
</ MenuItem >
< MenuItem href = "#export-orders" >
< IconArrowUpFill />
Export Orders
</ MenuItem >
</ MenuContent >
</ Menu >
)}
</>
)}
</ SidebarItem >
< SidebarItem tooltip = "Products" >
{({ isCollapsed , isFocused }) => (
<>
< SidebarLink href = "#" >
< IconCube />
< SidebarLabel >Products</ SidebarLabel >
</ SidebarLink >
{( ! isCollapsed || isFocused) && (
< Menu >
< MenuTrigger data-slot = "menu-action-trigger" aria-label = "Manage" >
< IconDotsHorizontal />
</ MenuTrigger >
< MenuContent popover = {{ offset: 0 , placement: "right top" }}>
< MenuItem href = "#new-product" >
< IconPlus />
Add New Product
</ MenuItem >
< MenuItem href = "#archive" >
< IconArchiveFill />
Archive Product
</ MenuItem >
< MenuItem href = "#manage-categories" >
< IconHashtagFill />
Manage Categories
</ MenuItem >
< MenuItem href = "#import" >
< IconArrowDownFill />
Import Products
</ MenuItem >
< MenuItem href = "#export" >
< IconArrowUpFill />
Export Products
</ MenuItem >
</ MenuContent >
</ Menu >
)}
</>
)}
</ SidebarItem >
< SidebarItem href = "#" badge = "4 Pending" tooltip = "Payments" >
< IconCreditCardFill />
< SidebarLabel >Payments</ SidebarLabel >
</ SidebarItem >
</ SidebarSection >
< SidebarDisclosureGroup defaultExpandedKeys = {[ 1 ]}>
< SidebarDisclosure id = { 1 }>
< SidebarDisclosureTrigger >
< IconDotsHorizontal />
< SidebarLabel >Support</ SidebarLabel >
</ SidebarDisclosureTrigger >
< SidebarDisclosurePanel >
< SidebarItem href = "#" tooltip = "Tickets" >
< IconTicketFill />
< SidebarLabel >Tickets</ SidebarLabel >
</ SidebarItem >
< SidebarItem href = "#" tooltip = "Chat Support" >
< IconMessageFill />
< SidebarLabel >Chat Support</ SidebarLabel >
</ SidebarItem >
< SidebarItem href = "#" tooltip = "FAQ" >
< IconCircleQuestionmarkFill />
< SidebarLabel >FAQ</ SidebarLabel >
</ SidebarItem >
< SidebarItem href = "#" tooltip = "Documentation" >
< IconNotesFill />
< SidebarLabel >Documentation</ SidebarLabel >
</ SidebarItem >
</ SidebarDisclosurePanel >
</ SidebarDisclosure >
< SidebarDisclosure id = { 2 }>
< SidebarDisclosureTrigger >
< IconPackageFill />
< SidebarLabel >Inventory</ SidebarLabel >
</ SidebarDisclosureTrigger >
< SidebarDisclosurePanel >
< SidebarItem href = "#" tooltip = "Warehouse" >
< IconBuildingFill />
< SidebarLabel >Warehouse</ SidebarLabel >
</ SidebarItem >
< SidebarItem href = "#" tooltip = "Stock Levels" >
< SidebarLabel >Stock Levels</ SidebarLabel >
</ SidebarItem >
< SidebarItem href = "#" tooltip = "Shipping" >
< SidebarLabel >Shipping</ SidebarLabel >
</ SidebarItem >
</ SidebarDisclosurePanel >
</ SidebarDisclosure >
</ SidebarDisclosureGroup >
</ SidebarSectionGroup >
</ SidebarContent >
< SidebarFooter className = "flex flex-row justify-between gap-4 group-data-[state=collapsed]:flex-col" >
< Menu >
< MenuTrigger className = "flex w-full items-center justify-between" aria-label = "Profile" >
< div className = "flex items-center gap-x-2" >
< Avatar
className = "size-8 *:size-8 group-data-[state=collapsed]:size-6 group-data-[state=collapsed]:*:size-6"
isSquare
src = "https://intentui.com/images/avatar/cobain.jpg"
/>
< div className = "in-data-[collapsible=dock]:hidden text-sm" >
< SidebarLabel >Kurt Cobain</ SidebarLabel >
< span className = "-mt-0.5 block text-muted-fg" >kurt@domain.com</ span >
</ div >
</ div >
< IconChevronsY data-slot = "chevron" />
</ MenuTrigger >
< MenuContent
className = "in-data-[sidebar-collapsible=collapsed]:min-w-56 min-w-(--trigger-width)"
placement = "bottom right"
>
< MenuSection >
< MenuHeader separator >
< span className = "block" >Kurt Cobain</ span >
< span className = "font-normal text-muted-fg" >@cobain</ span >
</ MenuHeader >
</ MenuSection >
< MenuItem href = "#dashboard" >
< IconDashboardFill />
Dashboard
</ MenuItem >
< MenuItem href = "#settings" >
< IconSettingsFill />
Settings
</ MenuItem >
< MenuItem href = "#security" >
< IconShieldFill />
Security
</ MenuItem >
< MenuSeparator />
< MenuItem href = "#contact" >
< IconHeadphonesFill />
Customer Support
</ MenuItem >
< MenuSeparator />
< MenuItem href = "#logout" >
< IconLogout />
Log out
</ MenuItem >
</ MenuContent >
</ Menu >
</ SidebarFooter >
< SidebarRail />
</ Sidebar >
< SidebarInset >
< SidebarNav >
< span className = "flex items-center gap-x-4" >
< SidebarTrigger className = "-ml-2" />
< Breadcrumbs className = "hidden md:flex" >
< Breadcrumbs.Item href = "/blocks/sidebar/sidebar-01" >Dashboard</ Breadcrumbs.Item >
< Breadcrumbs.Item >Newsletter</ Breadcrumbs.Item >
</ Breadcrumbs >
</ span >
< Menu >
< MenuTrigger className = "ml-auto md:hidden" aria-label = "Open Menu" >
< Avatar
isSquare
alt = "kurt cobain"
src = "https://intentui.com/images/avatar/cobain.jpg"
/>
</ MenuTrigger >
< MenuContent popover = {{ placement: "bottom end" }} className = "min-w-64" >
< MenuSection >
< MenuHeader separator >
< span className = "block" >Kurt Cobain</ span >
< span className = "font-normal text-muted-fg" >@cobain</ span >
</ MenuHeader >
</ MenuSection >
< MenuItem href = "#dashboard" >
< IconDashboard />
< MenuLabel >Dashboard</ MenuLabel >
</ MenuItem >
< MenuItem href = "#settings" >
< IconSettings />
< MenuLabel >Settings</ MenuLabel >
</ MenuItem >
< MenuSeparator />
< MenuItem >
< IconCommandRegular />
< MenuLabel >Command Menu</ MenuLabel >
</ MenuItem >
< MenuSeparator />
< MenuItem href = "#contact-s" >
< MenuLabel >Contact Support</ MenuLabel >
</ MenuItem >
< MenuSeparator />
< MenuItem href = "#logout" >
< IconLogout />
< MenuLabel >Log out</ MenuLabel >
</ MenuItem >
</ MenuContent >
</ Menu >
</ SidebarNav >
< div className = "p-4 lg:p-6" >{ /* Your content */ }</ div >
</ SidebarInset >
</ SidebarProvider >
CSS Variables
The sidebar just need one base color to work, the accent will generate from the base and the primary color just taking from the primary color you have. Make sure you have set evertyhing up, or hover into theme page to see the bunch of colors you can get. Too lazy? just copy the default color below to your stylesheet.
Copy Copied @theme inline {
-- color - sidebar : var (--sidebar);
-- color - sidebar - fg : var (--sidebar-fg);
-- color - sidebar - primary : var (--sidebar-primary);
-- color - sidebar - primary - fg : var (--sidebar-primary-fg);
-- color - sidebar - accent : var (--sidebar-accent);
-- color - sidebar - accent - fg : var (--sidebar-accent-fg);
-- color - sidebar - border : var (--sidebar-border);
-- color - sidebar - ring : var (--sidebar-ring);
}
:root {
-- sidebar : oklch ( 0.985 0 0 );
-- sidebar - fg : oklch ( 0.141 0.005 285.823 );
-- sidebar - primary : oklch ( 0.546 0.245 262.881 );
-- sidebar - primary - fg : oklch ( 1 0 0 );
-- sidebar - accent : oklch ( 0.92 0.004 286.32 );
-- sidebar - accent - fg : oklch ( 0.141 0.005 285.823 );
-- sidebar - border : oklch ( 0.901 0.006 286.286 );
-- sidebar - ring : oklch ( 0.546 0.245 262.881 );
}
.dark {
-- sidebar : oklch ( 0.180 0.006 285.885 );
-- sidebar - fg : oklch ( 0.985 0 0 );
-- sidebar - primary : oklch ( 0.546 0.245 262.881 );
-- sidebar - primary - fg : oklch ( 1 0 0 );
-- sidebar - accent : oklch ( 0.274 0.006 286.033 );
-- sidebar - accent - fg : oklch ( 0.985 0 0 );
-- sidebar - border : oklch ( 0.274 0.006 286.033 );
-- sidebar - ring : oklch ( 0.546 0.245 262.881 );
}
Not sure if it's your style, but it's a great starting point. If you’d like to tweak the colors, check out the theme customization page for more options.
Intent
The sidebar comes in three variations: "sidebar"
, "float"
, and "inset"
. By default, the variation is set to "sidebar"
.
The default variation is a traditional sidebar often used for navigation. Preview .
Copy Copied < Sidebar intent = "sidebar" />
Inset
The inset variation adds padding to the main content for a visually distinct layout. Explore the demo to see it in action, or switch to full-screen mode for a better view. Preview .
Copy Copied < Sidebar intent = "inset" />
Float
The float
variation introduces an inner border within the sidebar, while the wrapper includes padding around the content. Preview
Copy Copied < Sidebar intent = "float" />
Collapsible
The sidebar can be made collapsible by using the collapsible
prop in the SidebarProvider
. The default collapsible behavior is "hidden"
.
Hidden
When toggled, the sidebar hides completely from view. Preview
Copy Copied < Sidebar collapsible = "hidden" />
Dock
When toggled, the sidebar docks to a minimal state, showing only icons. Hovering over an icon reveals a tooltip with additional information. Preview
Copy Copied < Sidebar intent = "dock" />
Default Open
The sidebar’s initial state can be controlled using the defaultOpen
prop. For example, you can set defaultOpen
to false
and keep the sidebar docked.
Copy Copied < SidebarProvider defaultOpen = { false }>
< Sidebar collapsible = "dock" />
The sidebar section is a container for sidebar items. It accepts a label
prop, which will be displayed as a heading.
Copy Copied < SidebarSection >
< SidebarItem isCurrent href = "#" >
< SidebarLabel >Item 1</ SidebarLabel >
</ SidebarItem >
</ SidebarSection >
< SidebarSection label = "Other Section" >
< SidebarItem isCurrent href = "#" >
< SidebarLabel >Item 1</ SidebarLabel >
</ SidebarItem >
</ SidebarSection >
If you need to collapse multiple items, you can use the SidebarDisclosureGroup
component. Preview
Copy Copied {sections. map (( section , sectionIndex ) => (
< SidebarDisclosureGroup defaultExpandedKeys = {[ 1 , 2 ]} key = {sectionIndex}>
< SidebarDisclosure id = {sectionIndex + 1 }>
< SidebarDisclosureTrigger >
< section.icon />
< SidebarLabel > {section.label}</ SidebarLabel >
</ SidebarDisclosureTrigger >
< SidebarDisclosurePanel >
{section.items. map (( item , itemIndex ) => (
< SidebarItem key = {itemIndex} href = "#" >
{({ isHovered }) => (
<>
< i aria-hidden className = "content-center size-4" >
< IconBullet className = { `${ isHovered ? "fill-sky-500 text-sky-500" : ""} size-2 m-auto` } />
</ i >
< SidebarLabel >{item}</ SidebarLabel >
</>
)}
</ SidebarItem >
))}
</ SidebarDisclosurePanel >
</ SidebarDisclosure >
</ SidebarDisclosureGroup >
))}
const sections = [
{
icon: IconNotes,
label: "Blog" ,
items: [ "Articles" , "Categories" , "Tags" , "Comments" , "Authors" ]
},
{
icon: IconStore,
label: "Commerce" ,
items: [ "Orders" , "Products" , "Customers" , "Coupons" , "Discounts" ]
},
{
icon: IconWhiteboard,
label: "Analytics" ,
items: [ "Reports" , "Traffic" , "Conversions" , "Audience" , "Engagement" ]
},
{
icon: IconSettings,
label: "Settings" ,
items: [ "General" , "Profile" , "Billing" , "Notifications" , "Integrations" ]
}
]
The sidebar supports menus for displaying additional actions or options. When using a menu, be sure to include data-slot="menu-action-trigger"
.
Copy Copied < SidebarItem tooltip = "Orders" >
{({ isCollapsed , isFocused }) => (
<>
< SidebarLink href = "#" >
< IconShoppingBagFill />
< SidebarLabel >Orders</ SidebarLabel >
</ SidebarLink >
{( ! isCollapsed || isFocused) && (
< Menu >
< Menu.Trigger data-slot = "menu-action-trigger" aria-label = "Manage" >
< IconDotsHorizontal />
</ Menu.Trigger >
< Menu.Content popover = {{ offset: 0 , placement: "right top" }}>
< Menu.Item href = "#new-order" >
< IconPlus />
Create New Order
</ Menu.Item >
< Menu.Item href = "#view-all" >
< IconListBulletsFill />
View All Orders
</ Menu.Item >
< Menu.Item href = "#pending-orders" >
< IconClockFill />
Pending Orders
</ Menu.Item >
< Menu.Item href = "#completed-orders" >
< IconCircleCheckFill />
Completed Orders
</ Menu.Item >
< Menu.Item href = "#export-orders" >
< IconArrowUpFill />
Export Orders
</ Menu.Item >
</ Menu.Content >
</ Menu >
)}
</>
)}
</ SidebarItem >
Badge
The sidebar supports badges, which can be used to indicate the number of unread messages, tasks, or other items. Preview
Copy Copied < SidebarSection >
{navigation. map (( item , index ) => (
< SidebarItem key = {index} isCurrent = {item.isCurrent} href = "#" badge = {item?.badge}>
{item.icon}
< SidebarLabel >{item.label}</ SidebarLabel >
</ SidebarItem >
))}
</ SidebarSection >
const navigation = [
{ label: "Overview" , icon: < IconDashboard />, isCurrent: true , badge: undefined },
{ label: "Orders" , icon: < IconCart />, isCurrent: false , badge: 24 },
{ label: "Products" , icon: < IconCube />, isCurrent: false , badge: "31.51K" },
{ label: "Customers" , icon: < IconPeople />, isCurrent: false , badge: "12K" },
{ label: "Reports" , icon: < IconChartBar />, isCurrent: false , badge: 3 },
{ label: "Settings" , icon: < IconGear />, isCurrent: false , badge: undefined }
]
Separator
The sidebar supports separators, which can be used to separate sections or groups of items. Preview
Copy Copied < SidebarContent >
< SidebarSection />
< SidebarSeparator />
< SidebarSection />
< SidebarSection />
< SidebarSeparator />
< SidebarSectionGroup />
< SidebarSectionGroup />
< SidebarSeparator />
< SidebarSectionGroup />
</ SidebarContent >
The example previews will appear similar to the ones in the YouTube sidebar.
Loading source code...
The sidebar supports tooltips, which can be used to display additional information when you're on docked mode.
The sidebar supports headers, which can be used to display additional actions or options.
Copy Copied < Sidebar { ... props}>
< SidebarHeader >
< Link
className = "flex items-center group-data-[collapsible=dock]:size-10 group-data-[collapsible=dock]:justify-center gap-x-2"
href = "/docs/components/layouts/sidebar"
>
< IconBrandApple className = "size-5" />
< SidebarLabel className = "font-medium" >Intent UI</ SidebarLabel >
</ Link >
</ SidebarHeader >
...
</ Sidebar >
The sidebar supports footers, which can be used to display additional actions or options.
Copy Copied < Sidebar { ... props}>
...
< SidebarFooter >
< Menu >
< Menu.Trigger aria-label = "Profile" data-slot = "menu-trigger" >
< Avatar isSquare src = "https://intentui.com/images/avatar/cobain.jpg" />
< div className = "group-data-[collapsible=dock]:hidden text-sm" >
Kurt Cobain
< span className = "block -mt-0.5 text-muted-fg" >kurt@cobain.com</ span >
</ div >
< IconChevronLgDown className = "absolute right-3 transition-transform size-4 group-pressed:rotate-180" />
</ Menu.Trigger >
< Menu.Content placement = "bottom right" className = "min-w-(--trigger-width)" >
< Menu.Item />
</ Menu.Content >
</ Menu >
</ SidebarFooter >
</ Sidebar >
Side
The sidebar has two sides, left and right. You can set the side of the sidebar by using the side
prop. Preview
Copy Copied < Sidebar side = 'left | right' />
Loading source code...
Put Anything
You can put anything you want in it. You can use the SidebarContent
component to wrap your content. Let's try to add a range-calendar and search-field to the sidebar. Preview
Loading source code...
Remember state
To persist the sidebar’s state across sessions, wrap your layout with the SidebarProvider component. It stores the sidebar’s state in a cookie and restores it when the user revisits the page.
Copy Copied import { cookies } from "next/headers"
export default async function Layout ({ children } : Readonly <{ children : React . ReactNode }>) {
const cookieStore = await cookies ()
const sidebarState = cookieStore. get ( "sidebar_state" )
let defaultOpen = true
if (sidebarState) {
defaultOpen = sidebarState.value === "true"
}
return (
< SidebarProvider defaultOpen = {defaultOpen}>
Props
The sidebar supports the following props:
Property Type Default intent
"default" | "float" | "inset"
"default"
collapsible
"hidden" | "dock" | "none"
"hidden"
side
"left" | "right"
"left"
closeButton
boolean
"true"
Property Type state
"expanded" | "collapsed"
open
boolean
setOpen
(open: boolean) => void
isOpenOnMobile
boolean
setIsOpenOnMobile
(open: boolean) => void
isMobile
boolean
toggleSidebar
() => void
Property Type Default defaultOpen
boolean
true
isOpen
boolean
undefined
onOpenChange
(open: boolean) => void
undefined
shortcut
string "b"
Flexible blocks and templates Use ready-made blocks to craft unique pages without starting from scratch.
blocks.intentui.com