# Sidebar

A composable, keyboard accessible, and responsive sidebar component.

> For the complete documentation index, see [llms.txt](/llms.txt). Markdown variants are available by appending `.md` to any URL or sending an `Accept: text/markdown` header. An agent skill is available at [/.well-known/agent-skills/site-skill.md](/.well-known/agent-skills/site-skill.md).





<ComponentPreview name="sidebar-demo">
  <SidebarProvider className="!min-h-[400px] h-[400px]">
    <div className="flex w-full overflow-hidden rounded-none border h-full">
      <Sidebar className="absolute h-full" collapsible="icon">
        <SidebarContent>
          <SidebarGroup>
            <SidebarGroupLabel>
              Application
            </SidebarGroupLabel>

            <SidebarGroupContent>
              <SidebarMenu>
                {[
                                  { title: "Home", url: "#", icon: Home },
                                  { title: "Inbox", url: "#", icon: Inbox },
                                  { title: "Calendar", url: "#", icon: Calendar },
                                  { title: "Search", url: "#", icon: Search },
                                  { title: "Settings", url: "#", icon: Settings },
                                ].map((item) => (
                                  <SidebarMenuItem key={item.title}>
                                    <SidebarMenuButton asChild isActive={item.title === "Home"}>
                                      <a href={item.url}>
                                        <item.icon />
                                        <span>{item.title}</span>
                                      </a>
                                    </SidebarMenuButton>
                                  </SidebarMenuItem>
                                ))}
              </SidebarMenu>
            </SidebarGroupContent>
          </SidebarGroup>
        </SidebarContent>

        <SidebarFooter>
          <div className="flex justify-end group-data-[collapsible=icon]:justify-center p-2">
            <SidebarTrigger className="rounded-none" />
          </div>
        </SidebarFooter>
      </Sidebar>

      <SidebarInset className="bg-background flex flex-col flex-1 p-4 w-full h-full">
        <header className="flex items-center gap-2 mb-4 md:hidden">
          <SidebarTrigger />
        </header>

        <div className="flex flex-col gap-4 w-full">
          <div className="h-24 w-full rounded-none border-2 border-dashed" />

          <div className="h-64 w-full rounded-none border-2 border-dashed" />
        </div>
      </SidebarInset>
    </div>
  </SidebarProvider>
</ComponentPreview>

### Right-Side Layout [#right-side-layout]

<ComponentPreview name="sidebar-right">
  <SidebarProvider className="!min-h-[400px] h-[400px]">
    <div className="flex w-full overflow-hidden rounded-none border h-full relative">
      <SidebarInset className="bg-background flex flex-col flex-1 p-4 w-full h-full">
        <div className="flex flex-col gap-4 w-full">
          <h2 className="text-xl font-bold">
            Right Sidebar
          </h2>

          <div className="h-24 w-full rounded-none border-2 border-dashed" />
        </div>
      </SidebarInset>

      <Sidebar className="absolute h-full" side="right" collapsible="icon">
        <SidebarContent>
          <SidebarGroup>
            <SidebarGroupLabel>
              Options
            </SidebarGroupLabel>

            <SidebarGroupContent>
              <SidebarMenu>
                <SidebarMenuItem>
                  <SidebarMenuButton>
                    <Settings />

                    <span>
                      Configuration
                    </span>
                  </SidebarMenuButton>
                </SidebarMenuItem>
              </SidebarMenu>
            </SidebarGroupContent>
          </SidebarGroup>
        </SidebarContent>
      </Sidebar>
    </div>
  </SidebarProvider>
</ComponentPreview>

### Floating Variant [#floating-variant]

<ComponentPreview name="sidebar-floating">
  <SidebarProvider className="!min-h-[400px] h-[400px]">
    <div className="flex w-full overflow-hidden border bg-muted/20 h-full relative">
      <Sidebar className="absolute h-full" variant="floating">
        <SidebarContent>
          <SidebarGroup>
            <SidebarGroupLabel>
              Floating
            </SidebarGroupLabel>

            <SidebarGroupContent>
              <SidebarMenu>
                <SidebarMenuItem>
                  <SidebarMenuButton>
                    <Inbox />

                    <span>
                      Inbox
                    </span>
                  </SidebarMenuButton>
                </SidebarMenuItem>
              </SidebarMenu>
            </SidebarGroupContent>
          </SidebarGroup>
        </SidebarContent>
      </Sidebar>

      <SidebarInset className="bg-background flex flex-col flex-1 p-4 w-full h-full">
        <div className="flex flex-col gap-4 w-full">
          <h2 className="text-xl font-bold">
            Floating Sidebar Content
          </h2>

          <div className="h-64 w-full rounded-none border-2 border-dashed" />
        </div>
      </SidebarInset>
    </div>
  </SidebarProvider>
</ComponentPreview>

## Installation [#installation]

```bash
npx shadcn-ui@latest add sidebar
```

## Structure [#structure]

A typical Sidebar implementation requires a `SidebarProvider` to manage state across the page.

```tsx
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>
  )
}
```

## Usage [#usage]

Here is the anatomy of a `Sidebar` component.

```tsx
import {
  Sidebar,
  SidebarContent,
  SidebarFooter,
  SidebarGroup,
  SidebarHeader,
} from "@/components/ui/sidebar"

export function AppSidebar() {
  return (
    <Sidebar>
      <SidebarHeader />
      <SidebarContent>
        <SidebarGroup />
        <SidebarGroup />
      </SidebarContent>
      <SidebarFooter />
    </Sidebar>
  )
}
```

## Variants [#variants]

### SidebarInset [#sidebarinset]

If you want the main content to look "inset" with a background, you can wrap your main view in `SidebarInset`.

```tsx
import { SidebarInset, SidebarTrigger } from "@/components/ui/sidebar"

export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <SidebarProvider>
      <AppSidebar />
      <SidebarInset>
        <header>
          <SidebarTrigger />
        </header>
        <main>{children}</main>
      </SidebarInset>
    </SidebarProvider>
  )
}
```

## API Reference [#api-reference]

The `Sidebar` ecosystem exposes several properties to control its layout and behavior.

### SidebarProvider [#sidebarprovider]

| Prop           | Type       | Default | Description                                       |
| -------------- | ---------- | ------- | ------------------------------------------------- |
| `defaultOpen`  | `boolean`  | `true`  | The default open state of the sidebar.            |
| `open`         | `boolean`  | -       | The controlled open state.                        |
| `onOpenChange` | `function` | -       | Event handler called when the open state changes. |

### Sidebar [#sidebar]

| Prop          | Type                                 | Default       | Description                                        |
| ------------- | ------------------------------------ | ------------- | -------------------------------------------------- |
| `side`        | `"left" \| "right"`                  | `"left"`      | The side of the screen the sidebar is rendered on. |
| `variant`     | `"sidebar" \| "floating" \| "inset"` | `"sidebar"`   | The visual variant of the sidebar.                 |
| `collapsible` | `"offcanvas" \| "icon" \| "none"`    | `"offcanvas"` | The behavior when the sidebar is collapsed.        |

### useSidebar [#usesidebar]

The `useSidebar` hook returns the current context of the Sidebar:

| Prop            | Type                      | Description                                          |                                              |
| --------------- | ------------------------- | ---------------------------------------------------- | -------------------------------------------- |
| `state`         | \`"expanded"              | "collapsed"\`                                        | The current structural state of the sidebar. |
| `open`          | `boolean`                 | True if the sidebar is expanded.                     |                                              |
| `setOpen`       | `(open: boolean) => void` | Updates the open state.                              |                                              |
| `isMobile`      | `boolean`                 | True if the viewport is below the mobile breakpoint. |                                              |
| `openMobile`    | `boolean`                 | True if the mobile sidebar sheet is open.            |                                              |
| `setOpenMobile` | `(open: boolean) => void` | Updates the mobile sheet state.                      |                                              |
| `toggleSidebar` | `() => void`              | Toggles the sidebar between expanded and collapsed.  |                                              |

### SidebarMenuButton [#sidebarmenubutton]

| Prop       | Type                  | Default     | Description                                      |
| ---------- | --------------------- | ----------- | ------------------------------------------------ |
| `asChild`  | `boolean`             | `false`     | Render as a different element using Radix Slot.  |
| `isActive` | `boolean`             | `false`     | Sets the button to an active, highlighted state. |
| `variant`  | `enum`                | `"default"` | Visual variant (`default`, `outline`).           |
| `size`     | `enum`                | `"default"` | Button size (`default`, `sm`, `lg`).             |
| `tooltip`  | `string \| ReactNode` | -           | Tooltip content when the sidebar is collapsed.   |

### SidebarMenuItem [#sidebarmenuitem]

| Prop        | Type     | Default | Description             |
| ----------- | -------- | ------- | ----------------------- |
| `className` | `string` | -       | Additional CSS classes. |

### SidebarMenuAction [#sidebarmenuaction]

| Prop          | Type      | Default | Description                                                                    |
| ------------- | --------- | ------- | ------------------------------------------------------------------------------ |
| `showOnHover` | `boolean` | `false` | If true, the action only appears when the parent `SidebarMenuItem` is hovered. |

### Submenus [#submenus]

The Sidebar supports nested navigation using submenu components:

| Component              | Description                                        |
| ---------------------- | -------------------------------------------------- |
| `SidebarMenuSub`       | The container for a nested list of submenu items.  |
| `SidebarMenuSubItem`   | An individual item within a submenu.               |
| `SidebarMenuSubButton` | The button or link component for the submenu item. |

## Components [#components]

### SidebarGroup [#sidebargroup]

Use `SidebarGroup` to organize items into logical sections. It can contain a `SidebarGroupLabel`, `SidebarGroupContent`, and `SidebarGroupAction`.

### SidebarMenu [#sidebarmenu]

A structured `ul` for displaying `SidebarMenuItem` lists. The `SidebarMenuButton` handles hover states, active states, and accessibility properties.

## Accessibility [#accessibility]

The sidebar implements standard WAI-ARIA practices out of the box:

* Proper `aria-expanded` and `aria-controls` for the trigger.
* Full keyboard navigation across menus.
* Screen reader announcements when state changes.
* Follows the strict 150ms structural animation rules defined in `DESIGN.md`.
