---
title: Sidebar
description: A composable, themeable and customizable sidebar component. Created by Shadcn, animated by Animate UI, updated by malinskibeniamin.
icon: panel-left
author:
  name: malinskibeniamin
  url: https://github.com/malinskibeniamin
# Full-width iframe previews; the table of contents would sit on top of them.
mode: wide
---

<PoweredBy
  packages={[
    { name: 'Base UI', url: 'https://base-ui.com/react/components/dialog' },
    { name: 'Shadcn UI', url: 'https://ui.shadcn.com/docs/components/sidebar' },
    { name: 'Animate UI', url: 'https://animate-ui.com/docs/base/sidebar' },
    { name: 'Lucide', url: 'https://lucide.dev/' },
    { name: 'Motion', url: 'https://motion.dev/' },
  ]}
/>

### Installation

```package-install
npx shadcn@latest add @redpanda/sidebar
```

Requires React and ReactDOM **19.2+** for [`useEffectEvent`](https://react.dev/blog/2025/10/01/react-19-2#use-effect-event).

<figure className="flex flex-col gap-4">
  <ComponentPreview
    name="sidebar-demo"
    iframe
    wide
    title="Sidebar"
    type="block"
    description="A composable, themeable and customizable sidebar component built using shadcn/ui"
    className="w-full"
  />
  <figcaption className="text-center text-sm text-subtle">A sidebar that collapses to icons.</figcaption>
</figure>

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.

```tsx
<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:

```mermaid
graph TD;
    A[❓ Need navigation/tools?] --> B{Always visible?};
    A --> C[⚠️ Use other navigation patterns];
    B --> D[✅ Use Sidebar Component];
    B --> E{Conditional visibility?};
    D --> F{Collapsible or fixed?};
    E --> G[⚠️ Consider Sheet or Drawer];
    F --> H[✅ Collapsible Sidebar];
    F --> I[✅ Fixed Sidebar];

    classDef recommended fill:#4ade80,stroke:#22c55e,stroke-width:2px,color:#000;
    classDef discouraged fill:#fbbf24,stroke:#f59e0b,stroke-width:2px,color:#000;
    classDef decision fill:#60a5fa,stroke:#3b82f6,stroke-width:2px,color:#fff;
    classDef neutral fill:#9ca3af,stroke:#6b7280,stroke-width:2px,color:#fff;

    class D,H,I recommended;
    class C,G discouraged;
    class A,B,E,F decision;
```

## Usage

```tsx expandable
<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

<div className="flex flex-row gap-x-3">
  <ExternalLink href="https://ui.shadcn.com/docs/components/sidebar" text="Docs" />
</div>

### Animate UI props

#### Sidebar

| Prop | Type | Default | Description |
| - | - | - | - |
| `containerClassName?` | `string` | - | The class name of the sidebar container |
| `animateOnHover?` | `boolean` | `true` | Whether to animate the sidebar on hover |
| `transition?` | `Transition` | `{ type: "spring", stiffness: 350, damping: 35 }` | The transition of the sidebar |

### Examples

#### Loading skeleton

<figure className="flex flex-col gap-4">
  <ComponentPreview
    name="sidebar-loading-skeleton-demo"
    title="Sidebar loading skeleton"
    description="Skeleton nav rows with random widths (default) or uniform full-width rows"
    className="w-full"
  />
  <figcaption className="text-center text-sm text-subtle">
    `SidebarMenuSkeleton` renders random per-row widths by default. Pass `uniform` for full-width rows that match evenly
    sized nav items.
  </figcaption>
</figure>

#### Wide content in the inset

<figure className="flex flex-col gap-4">
  <ComponentPreview
    name="sidebar-wide-content-demo"
    iframe
    wide
    title="Sidebar with wide content"
    type="block"
    description="A block wider than the inset scrolls itself instead of the page"
    className="w-full"
  />
  <figcaption className="text-center text-sm text-subtle">
    `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.
  </figcaption>
</figure>

#### With a fixed banner

<figure className="flex flex-col gap-4">
  <ComponentPreview
    name="sidebar-with-banner-demo"
    iframe
    wide
    title="Sidebar with banner"
    type="block"
    description="Sidebar paired with a fixed top banner via bannerHeight"
    className="w-full"
  />
  <figcaption className="text-center text-sm text-subtle">
    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.
  </figcaption>
</figure>

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

<figure className="flex flex-col gap-4">
  <ComponentPreview
    name="sidebar-cloud-demo"
    iframe
    wide
    title="Sidebar Cloud UI"
    type="block"
    description="Example sidebar for Cloud UI"
    className="w-full"
  />
  <figcaption className="text-center text-sm text-subtle">An example sidebar representation for Cloud UI.</figcaption>
</figure>

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

<figure className="flex flex-col gap-4">
  <ComponentPreview
    name="sidebar-cloud-billing-credits-demo"
    iframe
    wide
    title="Sidebar Cloud UI"
    type="block"
    description="Example sidebar for Cloud UI with billing credits"
    className="w-full"
  />
  <figcaption className="text-center text-sm text-subtle">
    An example sidebar representation for Cloud UI with billing credits for a free trial.
  </figcaption>
</figure>

#### Cloud UI (With Billing expired)

<figure className="flex flex-col gap-4">
  <ComponentPreview
    name="sidebar-cloud-billing-demo"
    iframe
    wide
    title="Sidebar Cloud UI"
    type="block"
    description="Example sidebar for Cloud UI with billing expired"
    className="w-full"
  />
  <figcaption className="text-center text-sm text-subtle">
    An example sidebar representation for Cloud UI with billing free trial expired.
  </figcaption>
</figure>

#### Cloud UI (Cluster)

<figure className="flex flex-col gap-4">
  <ComponentPreview
    name="sidebar-cloud-cluster-demo"
    iframe
    wide
    title="Sidebar Cloud UI within a cluster"
    type="block"
    description="Example sidebar for Cloud UI within a cluster"
    className="w-full"
  />
  <figcaption className="text-center text-sm text-subtle">
    An example sidebar representation for Cloud UI within a cluster.
  </figcaption>
</figure>

#### Cloud UI (Serverless)

<figure className="flex flex-col gap-4">
  <ComponentPreview
    name="sidebar-cloud-serverless-demo"
    iframe
    wide
    title="Sidebar Cloud UI within a serverless cluster"
    type="block"
    description="Example sidebar for Cloud UI within a serverless cluster"
    className="w-full"
  />
  <figcaption className="text-center text-sm text-subtle">
    An example sidebar representation for Cloud UI within a serverless cluster.
  </figcaption>
</figure>

#### Console UI

<figure className="flex flex-col gap-4">
  <ComponentPreview
    name="sidebar-console-demo"
    iframe
    wide
    title="Sidebar Console UI"
    type="block"
    description="Example sidebar for Console UI"
    className="w-full"
  />
  <figcaption className="text-center text-sm text-subtle">An example sidebar representation for Console UI.</figcaption>
</figure>

#### Console UI (Self-hosted)

<figure className="flex flex-col gap-4">
  <ComponentPreview
    name="sidebar-console-self-hosted-demo"
    iframe
    wide
    title="Sidebar self-hosted Console UI"
    type="block"
    description="Example sidebar for self-hosted Console UI"
    className="w-full"
  />
  <figcaption className="text-center text-sm text-subtle">
    An example sidebar representation for self-hosted Console UI.
  </figcaption>
</figure>

#### Admin UI

<figure className="flex flex-col gap-4">
  <ComponentPreview
    name="sidebar-admin-demo"
    iframe
    wide
    title="Sidebar Admin UI"
    type="block"
    description="Example sidebar for Admin UI"
    className="w-full"
  />
  <figcaption className="text-center text-sm text-subtle">An example sidebar representation for Admin UI.</figcaption>
</figure>

## Credits

- We take our inspiration from [Shadcn UI](https://ui.shadcn.com/docs/components/sidebar) for the sidebar component and styling.
- We use [Animate UI](https://github.com/animate-ui/animate-ui) from [imskyleen](https://github.com/imskyleen) for all the animations.
