Layouts

Sidebar

A collapsible side panel for navigation or extra content, with multiple intents, behaviors, and customization options to match your layout on any screen size

Installation

Install the component via the CLI in one command.

npx shadcn@latest add @intentui/sidebar

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.

Manual installation

Use this approach if you prefer to install and wire up the component yourself instead of using the CLI.

npm install react-aria-components @heroicons/react tailwind-merge

CSS variables

The sidebar just needs one base color to work; the accent is generated from the base, and the primary color is taken from the primary color you already have. Make sure you have set everything up, or head to the theme page to see the colors you can use. Too lazy? Just copy the default color below to your stylesheet.

@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.623 0.214 259.815 / 0.15);
  --sidebar-primary-fg: oklch(0.488 0.243 264.376);
  --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.21 0.006 285.885);
  --sidebar-fg: oklch(0.985 0 0);
  --sidebar-primary: oklch(0.623 0.214 259.815 / 0.1);
  --sidebar-primary-fg: oklch(0.707 0.165 254.624);
  --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.

Examples

Intent

The sidebar comes in three variations: sidebar, float, and inset. By default, the variation is set to "sidebar".

Default

The default variation is a traditional sidebar often used for navigation. Preview.

<Sidebar intent="default" />

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.

<Sidebar intent="inset" />

Float

The float variation introduces an inner border within the sidebar, while the wrapper includes padding around the content. Preview

<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

<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

<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.

<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.

<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

<SidebarDisclosureGroup defaultExpandedKeys={[1]}>
  <SidebarDisclosure id={1}>
    <SidebarDisclosureTrigger>
      <EllipsisHorizontalIcon />
      <SidebarLabel>Support</SidebarLabel>
    </SidebarDisclosureTrigger>
    <SidebarDisclosurePanel>
      <SidebarItem href="#" tooltip="Tickets">
        <TicketIcon />
        <SidebarLabel>Tickets</SidebarLabel>
      </SidebarItem>
      <SidebarItem href="#" tooltip="Chat Support">
        <ChatBubbleLeftRightIcon />
        <SidebarLabel>Chat Support</SidebarLabel>
      </SidebarItem>
      <SidebarItem href="#" tooltip="FAQ">
        <QuestionMarkCircleIcon />
        <SidebarLabel>FAQ</SidebarLabel>
      </SidebarItem>
      <SidebarItem href="#" tooltip="Documentation">
        <DocumentTextIcon />
        <SidebarLabel>Documentation</SidebarLabel>
      </SidebarItem>
    </SidebarDisclosurePanel>
  </SidebarDisclosure>
  <SidebarDisclosure id={2}>
    <SidebarDisclosureTrigger>
      <ArchiveBoxIcon />
      <SidebarLabel>Inventory</SidebarLabel>
    </SidebarDisclosureTrigger>
    <SidebarDisclosurePanel>
      <SidebarItem href="#" tooltip="Warehouse">
        <BuildingOfficeIcon />
        <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>

The sidebar supports menus for displaying additional actions or options.

<SidebarItem tooltip="Orders">
  {({ isCollapsed, isFocused }) => (
    <>
      <SidebarLink href="#">
        <SidebarLabel>Orders</SidebarLabel>
      </SidebarLink>
      {(!isCollapsed || isFocused) && (
        <Menu>
          <SidebarMenuTrigger aria-label="Manage">
            <EllipsisHorizontalIcon />
          </MenuTrigger>
          <MenuContent popover={{ offset: 0, placement: "right top" }}>
            <MenuItem href="#new-order">
              <PlusIcon />
              Create New Order
            </MenuItem>
            <MenuItem href="#view-all">
              View All Orders
            </MenuItem>
            <MenuItem href="#pending-orders">
              Pending Orders
            </MenuItem>
            <MenuItem href="#completed-orders">
              Completed Orders
            </MenuItem>
            <MenuItem href="#export-orders">
              Export Orders
            </MenuItem>
          </MenuContent>
        </Menu>
      )}
    </>
  )}
</SidebarItem>

By default, the sidebar menu trigger will be visible when you hover over the sidebar item. If you want to always show the menu trigger, you can use the alwaysVisible prop.

<SidebarMenuTrigger alwaysVisible aria-label="Manage">
  <EllipsisHorizontalIcon />
</SidebarMenuTrigger>

Badge

The sidebar supports badges, which can be used to indicate the number of unread messages, tasks, or other items. Preview

<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: <HomeIcon />, isCurrent: true, badge: undefined },
  { label: "Products", icon: <CubeIcon />, isCurrent: false, badge: "31.51K" },
]

Separator

The sidebar supports separators, which can be used to separate sections or groups of items. Preview

<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...

Tooltip

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.

<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"
    >
      <SidebarLabel className="font-medium">Intent UI</SidebarLabel>
    </Link>
  </SidebarHeader>
  ...
</Sidebar>

The sidebar supports footers, which can be used to display additional actions or options.

<Sidebar {...props}>
  ...
  <SidebarFooter>
    <Menu>
      <MenuTrigger aria-label="Profile">
        <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">@cobain</span>
        </div>
        <ChevronDownIcon className="absolute right-3 transition-transform size-4 group-pressed:rotate-180" />
      </MenuTrigger>
      <MenuContent placement="bottom right" className="min-w-(--trigger-width)">
        <MenuItem/>
      </MenuContent>
    </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

<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.

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}>

Component API

The Sidebar component renders an application side navigation panel.

PropTypeDefault
classNamestring-
closeButtonbooleantrue
collapsible"hidden" | "dock" | "none"hidden
intent"default" | "float" | "inset"default
side"left" | "right"left

SidebarContent

The SidebarContent component wraps the main sidebar content.

PropTypeDefault
classNamestring-

SidebarDisclosure

The SidebarDisclosure component wraps a collapsible sidebar item.

PropTypeDefault
classNamestring-

SidebarDisclosureGroup

The SidebarDisclosureGroup component groups collapsible sidebar items.

PropTypeDefault
classNamestring-

SidebarDisclosurePanel

The SidebarDisclosurePanel component contains collapsible sidebar content.

PropTypeDefault
classNamestring-

SidebarDisclosureTrigger

The SidebarDisclosureTrigger component toggles sidebar disclosure content.

PropTypeDefault
classNamestring-

SidebarFooter

The SidebarFooter component renders footer content in the sidebar.

PropTypeDefault
classNamestring-

SidebarHeader

The SidebarHeader component renders header content in the sidebar.

PropTypeDefault
classNamestring-

SidebarInset

The SidebarInset component aligns page content next to the sidebar.

PropTypeDefault
classNamestring-

SidebarItem

The SidebarItem component represents one sidebar link or action.

PropTypeDefault
badgestring | number | undefined-
classNamestring-
isCurrentboolean-
tooltipstring | React.ComponentProps<typeof TooltipContent>-

SidebarLabel

The SidebarLabel component renders text inside a sidebar item.

PropTypeDefault
classNamestring-

The SidebarLink component renders a sidebar link.

PropTypeDefault
classNamestring-

SidebarMenuTrigger

The SidebarMenuTrigger component renders a sidebar menu trigger.

PropTypeDefault
alwaysVisiblebooleanfalse
classNamestring-

SidebarNav

The SidebarNav component wraps sidebar navigation content.

PropTypeDefault
classNamestring-
isStickybooleanfalse

SidebarProvider

The SidebarProvider component manages sidebar open state.

PropTypeDefault
classNamestring-
defaultOpenbooleantrue
isOpenboolean-
onOpenChange(open: boolean) => void-
shortcutstringb

SidebarRail

The SidebarRail component renders the collapsed sidebar rail.

PropTypeDefault
classNamestring-

SidebarSection

The SidebarSection component groups sidebar items.

PropTypeDefault
classNamestring-
labelstring-

SidebarSectionGroup

The SidebarSectionGroup component groups sidebar sections.

PropTypeDefault
classNamestring-

SidebarSeparator

The SidebarSeparator component separates sidebar content.

PropTypeDefault
classNamestring-

SidebarTree

The SidebarTree component renders nested sidebar navigation.

PropTypeDefault
classNamestring-

SidebarTreeContent

The SidebarTreeContent component renders content inside a sidebar tree item.

PropTypeDefault
classNamestring-
isCurrentboolean-

SidebarTreeItem

The SidebarTreeItem component represents one sidebar tree item.

PropTypeDefault
classNamestring-

SidebarTrigger

The SidebarTrigger component toggles the sidebar.

PropTypeDefault
classNamestring-
Unlock the full power of
Intent UI Design

Build modern web apps faster with 1000+ resources across components, blocks, patterns, templates, and starter kits.

Learn more