Main content area
<Sidebar.Provider defaultOpen>
  <Sidebar>
    <Sidebar.Content>
      <Sidebar.Group>
        <Sidebar.GroupLabel>Overview</Sidebar.GroupLabel>
        <Sidebar.Menu>
          <Sidebar.MenuButton icon={HouseIcon} active>Home</Sidebar.MenuButton>
          <Sidebar.MenuButton icon={GlobeIcon}>Domains</Sidebar.MenuButton>
        </Sidebar.Menu>
      </Sidebar.Group>
    </Sidebar.Content>
  </Sidebar>
</Sidebar.Provider>

Installation

Barrel

import { Sidebar } from "@cloudflare/kumo";

Granular

import { Sidebar } from "@cloudflare/kumo/components/sidebar";

Usage

At minimum you need Provider, Sidebar, Content (scrollable area), Menu, and MenuButton. Add Header / Footer to pin content above or below the scroll area. Use Group + GroupLabel to organize sections.

import { Sidebar } from "@cloudflare/kumo";
import { HouseIcon, CodeIcon, GearIcon } from "@phosphor-icons/react";

function AppLayout({ children }) {
  return (
    <Sidebar.Provider defaultOpen>
      <Sidebar>
        <Sidebar.Content>
          <Sidebar.Group>
            <Sidebar.GroupLabel>Navigation</Sidebar.GroupLabel>
            <Sidebar.Menu>
              <Sidebar.MenuButton icon={HouseIcon} active>Home</Sidebar.MenuButton>
              {/* MenuItem only needed to wrap Collapsible */}
              <Sidebar.MenuItem>
                <Sidebar.Collapsible>
                  <Sidebar.CollapsibleTrigger
                    render={
                      <Sidebar.MenuButton icon={CodeIcon}>
                        Compute <Sidebar.MenuChevron />
                      </Sidebar.MenuButton>
                    }
                  />
                  <Sidebar.CollapsibleContent>
                    <Sidebar.MenuSub>
                      <Sidebar.MenuSubButton>Workers</Sidebar.MenuSubButton>
                    </Sidebar.MenuSub>
                  </Sidebar.CollapsibleContent>
                </Sidebar.Collapsible>
              </Sidebar.MenuItem>
            </Sidebar.Menu>
          </Sidebar.Group>
        </Sidebar.Content>
        <Sidebar.Footer>
          <Sidebar.MenuButton icon={GearIcon}>Settings</Sidebar.MenuButton>
        </Sidebar.Footer>
      </Sidebar>
      <div className="flex-1">{children}</div>
    </Sidebar.Provider>
  );
}

Examples

Basic

The minimum viable sidebar: just groups, menu buttons, and collapsible sub-menus. No header or footer. MenuButton and MenuSubButton auto-wrap in <li> — no MenuItem / MenuSubItem needed.

Main content area
<Sidebar.Provider defaultOpen>
  <Sidebar>
    <Sidebar.Content>
      <Sidebar.Group>
        <Sidebar.GroupLabel>Overview</Sidebar.GroupLabel>
        <Sidebar.Menu>
          <Sidebar.MenuButton icon={HouseIcon} active>Home</Sidebar.MenuButton>
          <Sidebar.MenuButton icon={ChartBarIcon}>Analytics</Sidebar.MenuButton>
        </Sidebar.Menu>
      </Sidebar.Group>
    </Sidebar.Content>
  </Sidebar>
</Sidebar.Provider>

Toggle & Collapsed State

Use Sidebar.Trigger in the footer or useSidebar().toggleSidebar programmatically. Pass tooltip to show labels on hover when collapsed.

Click the button or the sidebar trigger to toggle

<Sidebar.MenuButton icon={HouseIcon} tooltip="Home" active>
  Home
</Sidebar.MenuButton>

<Sidebar.Footer>
  <Sidebar.Trigger />
</Sidebar.Footer>

// Or programmatically:
const { toggleSidebar } = useSidebar();

Resizable

Drag the edge to resize. Dragging below minWidth collapses; dragging outward from collapsed expands.

Drag the sidebar edge to resize

<Sidebar.Provider defaultOpen resizable defaultWidth={240} minWidth={180} maxWidth={400}>
  <Sidebar>
    <Sidebar.Content>...</Sidebar.Content>
    <Sidebar.ResizeHandle />
  </Sidebar>
</Sidebar.Provider>

Right Side

Use side="right" for a sidebar on the right edge. Place <main> before <Sidebar> in the DOM.

Main content area
<Sidebar.Provider defaultOpen side="right">
  <main className="flex-1">...</main>
  <Sidebar>
    <Sidebar.Content>
      <Sidebar.Group>
        <Sidebar.GroupLabel>Details</Sidebar.GroupLabel>
        <Sidebar.Menu>
          <Sidebar.MenuButton icon={GearIcon} active>Properties</Sidebar.MenuButton>
          <Sidebar.MenuButton icon={ChartBarIcon}>Metrics</Sidebar.MenuButton>
        </Sidebar.Menu>
      </Sidebar.Group>
    </Sidebar.Content>
  </Sidebar>
</Sidebar.Provider>

Peeking

Set peekable on the Provider. When the sidebar is collapsed, hovering or focusing it temporarily expands it. Moving away collapses it back. The data-state attribute will be "peeking" during the peek.

State: Expanded

Collapse, then hover the sidebar to peek

<Sidebar.Provider defaultOpen peekable>
  <Sidebar>
    <Sidebar.Content>...</Sidebar.Content>
    <Sidebar.Footer>
      <Sidebar.Trigger />
    </Sidebar.Footer>
  </Sidebar>
</Sidebar.Provider>

// Read peeking state:
const { state, isPeeking } = useSidebar();
// state: "expanded" | "collapsed" | "peeking"

Keyboard Shortcut

Pass keyboardShortcut to the Provider to toggle the sidebar with a keyboard shortcut. Use "mod+b" for Cmd+B on Mac / Ctrl+B elsewhere.

B

Press Cmd+B (Mac) or Ctrl+B to toggle

<Sidebar.Provider defaultOpen keyboardShortcut="mod+b">
  <Sidebar>...</Sidebar>
</Sidebar.Provider>

Sliding Views

Use Sidebar.SlidingViews and Sidebar.SlidingView for animated horizontal transitions between navigation surfaces (e.g., account ↔ zone). Inactive views are automatically marked with aria-hidden and inert. Animation respects prefers-reduced-motion.

Active: Account surface

Click the header button to slide between views

const [surface, setSurface] = useState("account");

<Sidebar.SlidingViews activeKey={surface} direction="left">
  <Sidebar.SlidingView value="account">
    <Sidebar.Content>...account nav...</Sidebar.Content>
  </Sidebar.SlidingView>
  <Sidebar.SlidingView value="zone">
    <Sidebar.Content>...zone nav...</Sidebar.Content>
  </Sidebar.SlidingView>
</Sidebar.SlidingViews>

Full Example

Kitchen sink showcasing every subcomponent: header with account switcher, groups with labels, collapsible sections with nested expandable, badges, sliding views, and a footer trigger.

Main content area
<Sidebar>
  <Sidebar.Header>
    <AccountSwitcher />
  </Sidebar.Header>
  <Sidebar.Content>
    <Sidebar.Group>
      <Sidebar.Menu>
        <Sidebar.MenuButton icon={HouseIcon} active>Home</Sidebar.MenuButton>
      </Sidebar.Menu>
    </Sidebar.Group>
    <Sidebar.Group>
      <Sidebar.GroupLabel>Build</Sidebar.GroupLabel>
      <Sidebar.Menu>
        <Sidebar.MenuItem>
          <Sidebar.Collapsible defaultOpen>
            <Sidebar.CollapsibleTrigger
              render={
                <Sidebar.MenuButton icon={CodeIcon}>
                  Compute <Sidebar.MenuChevron />
                </Sidebar.MenuButton>
              }
            />
            <Sidebar.CollapsibleContent>
              <Sidebar.MenuSub>
                <Sidebar.MenuSubItem>
                  <Sidebar.Collapsible>
                    <Sidebar.CollapsibleTrigger
                      render={
                        <Sidebar.MenuSubButton>
                          Workers & Pages <Sidebar.MenuChevron />
                        </Sidebar.MenuSubButton>
                      }
                    />
                    <Sidebar.CollapsibleContent>
                      <Sidebar.MenuSub>
                        <Sidebar.MenuSubButton>Overview</Sidebar.MenuSubButton>
                      </Sidebar.MenuSub>
                    </Sidebar.CollapsibleContent>
                  </Sidebar.Collapsible>
                </Sidebar.MenuSubItem>
                <Sidebar.MenuSubButton>
                  Containers <Sidebar.MenuBadge>Beta</Sidebar.MenuBadge>
                </Sidebar.MenuSubButton>
              </Sidebar.MenuSub>
            </Sidebar.CollapsibleContent>
          </Sidebar.Collapsible>
        </Sidebar.MenuItem>
      </Sidebar.Menu>
    </Sidebar.Group>
    <Sidebar.Group>
      <Sidebar.GroupLabel>Protect</Sidebar.GroupLabel>
      <Sidebar.Menu>
        <Sidebar.MenuButton icon={ShieldCheckIcon}>Security</Sidebar.MenuButton>
      </Sidebar.Menu>
    </Sidebar.Group>
  </Sidebar.Content>
  <Sidebar.Footer>
    <Sidebar.Trigger />
  </Sidebar.Footer>
</Sidebar>

API Reference

Sidebar

The main sidebar container. Renders as <aside> on desktop, Dialog sheet on mobile.

PropTypeDefaultDescription
defaultOpenboolean-Initial open state when uncontrolled.
openboolean-Controlled open state.
variant"sidebar" | "floating" | "inset""sidebar"Sidebar layout variant.
side"left" | "right""left"Which side the sidebar is on.
collapsible"icon" | "offcanvas" | "none""icon"-
resizableboolean-Enable drag-to-resize on the sidebar edge.
defaultWidthnumber-Initial width in pixels when resizable.
minWidthnumber-Minimum width in pixels when resizing.
maxWidthnumber-Maximum width in pixels when resizing.
childrenReactNode-Content — typically `<Sidebar>` + main content.
classNamestring-Additional CSS classes for the wrapper div.

Sidebar.Provider

Context provider managing expand/collapse state and mobile detection.

PropTypeDefault
defaultOpenboolean-
openboolean-
variantSidebarVariant-
sideSidebarSide-
collapsible"icon" | "offcanvas" | "none"-
resizableboolean-
defaultWidthnumber-
minWidthnumber-
maxWidthnumber-
children*ReactNode-
classNamestring-

Sidebar.Content

Scrollable middle section (flex-1 overflow-y-auto). Use Header / Footer to pin content above or below this scroll area.

Sidebar.MenuButton

Primary interactive element. Supports icons, active state, links, and auto-tooltip when collapsed. Auto-wraps in <li> — no MenuItem wrapper needed unless wrapping a Collapsible.

PropTypeDefault

No component-specific props. Accepts standard HTML attributes.

Sidebar.MenuSubButton

Button inside a sub-menu for nested navigation. Auto-wraps in <li> — no MenuSubItem wrapper needed.

PropTypeDefault

No component-specific props. Accepts standard HTML attributes.

Sidebar.GroupContent

Animation wrapper — only needed for collapsible groups (provides the grid-rows height animation). For non-collapsible groups, place Menu directly inside Group.