Sidebar

A slide-out drawer with backdrop overlay, smooth animations, and keyboard dismiss support.

9:41

Usage

app.tsx
1import { useState } from "react";
2import { AppShell, Header, Content, Sidebar, NavGroup, NavItem } from "appshell-react";
3import { Menu, Home, Settings, User, X } from "lucide-react";
4
5export default function App() {
6 const [open, setOpen] = useState(false);
7
8 return (
9 <AppShell safeArea>
10 <Header
11 behavior="fixed"
12 logo={
13 <button onClick={() => setOpen(true)}>
14 <Menu className="size-5" />
15 </button>
16 }
17 />
18
19 <Sidebar open={open} onClose={() => setOpen(false)} side="left">
20 <div className="flex items-center justify-between p-4 border-b">
21 <span className="font-bold">Menu</span>
22 <button onClick={() => setOpen(false)}>
23 <X className="size-4" />
24 </button>
25 </div>
26
27 <NavGroup title="Navigation" defaultOpen>
28 <NavItem label="Home" icon={<Home />} active />
29 <NavItem label="Profile" icon={<User />} />
30 <NavItem label="Settings" icon={<Settings />} />
31 </NavGroup>
32 </Sidebar>
33
34 <Content className="p-4">
35 {/* Your content */}
36 </Content>
37 </AppShell>
38 );
39}

Right Side

The sidebar can slide from either side:

tsx
1<Sidebar open={open} onClose={() => setOpen(false)} side="right">
2 {/* Sidebar content */}
3</Sidebar>

Sidebar Props

PropTypeDefaultDescription
openbooleanfalseWhether the sidebar is open
onClose() => void-Callback when sidebar should close
side"left" | "right""left"Which side to slide from
classNamestring-Additional CSS classes
childrenReactNode-Sidebar content

NavGroup Props

PropTypeDefaultDescription
titlestring-Group title
defaultOpenbooleantrueWhether group is expanded by default
childrenReactNode-NavItem components

NavItem Props

PropTypeDefaultDescription
labelstring-Item label
iconReactNode-Icon element
activebooleanfalseWhether this item is active
badgenumber | string-Badge count or text
onClick() => void-Click handler
hrefstring-Link destination

Keyboard Support

The Sidebar automatically handles keyboard interactions:

  • Escape closes the sidebar
  • Focus is trapped inside the sidebar when open
  • Focus returns to the trigger element when closed