Vertical Sidebar
Side navigation with collapsible layout, sectioned items, badges, counts, and a user profile footer.
Preview
Sidebar in context — a realistic 3-column application shell
dashboard
Collapsible
Toggle between expanded (labels visible) and collapsed (icon-only) states
The preview above reflects the current state. Collapsed mode preserves icons and tooltips.
Variants
Default, compact, and minimal layouts side by side
Default
Compact
Minimal
Anatomy
The building blocks that make up a vertical sidebar
Header
Logo, brand name, and optional collapse toggle
Nav sections
Grouped items with uppercase section labels
Item
Icon, label, optional badge or count, active indicator
User footer
Avatar, name, email — anchored to the bottom
Pairs well with
Related layout patterns
Props
Component API reference
| Prop | Type | Default | Description |
|---|---|---|---|
items* | NavItem[] | — | Main navigation items |
secondaryItems | NavItem[] | — | Secondary navigation items |
activeItem | string | — | Currently active item id |
onSelect | (id: string) => void | — | Item select callback |
collapsed | boolean | false | Collapsed (icon-only) state |
onCollapsedChange | (collapsed: boolean) => void | — | Collapse toggle callback |
user | UserInfo | — | User info for footer section |
logo | ReactNode | — | Custom logo component |
variant | 'default' | 'compact' | 'minimal' | 'default' | Visual variant |
className | string | — | Additional CSS classes |
Usage
Import and implementation examples
import { useState } from 'react'import Link from 'next/link'import { Home, Users, Settings } from 'lucide-react'import { cn } from '@/lib/utils'import { Button } from '@/components/ui/button'import { Badge } from '@/components/ui/badge'import { Avatar, AvatarFallback } from '@/components/ui/avatar'
const navItems = [ { id: 'home', label: 'Home', icon: Home }, { id: 'team', label: 'Team', icon: Users, count: 12 }, { id: 'settings', label: 'Settings', icon: Settings },]
export function Sidebar() { const [active, setActive] = useState('home')
return ( <aside className="w-60 bg-white dark:bg-slate-900 border-r border-border-default flex flex-col h-screen"> {/* Header */} <div className="h-14 px-4 border-b border-border-default flex items-center gap-2"> <div className="w-7 h-7 rounded-lg bg-primary-default" /> <span className="font-semibold text-foreground-default">My App</span> </div>
{/* Nav */} <nav className="flex-1 p-3"> <ul className="space-y-0.5"> {navItems.map(({ id, label, icon: Icon, count }) => ( <li key={id}> <button onClick={() => setActive(id)} aria-current={active === id ? 'page' : undefined} className={cn( 'w-full flex items-center gap-2.5 px-3 py-2 rounded-lg text-sm', active === id ? 'bg-indigo-50 dark:bg-indigo-950/50 text-primary-default font-medium' : 'text-foreground-subtle hover:bg-slate-50 dark:hover:bg-slate-800' )} > <Icon className="w-4 h-4 shrink-0" /> <span className="flex-1 text-left">{label}</span> {count && <span className="text-xs text-foreground-muted">{count}</span>} </button> </li> ))} </ul> </nav>
{/* User */} <div className="p-3 border-t border-border-default"> <div className="flex items-center gap-2 p-2"> <Avatar size="sm"> <AvatarFallback>JS</AvatarFallback> </Avatar> <div className="flex-1 min-w-0"> <p className="text-sm font-medium truncate">Jens Scholtanus</p> <p className="text-xs text-foreground-muted truncate">jens@app.io</p> </div> </div> </div> </aside> )}Built With
3 componentsThis block uses the following UI components from the design system:
Features
Built-in functionality
- Collapsible: Toggle between expanded (240px) and icon-only (64px) modes
- Sectioned nav: Group items with uppercase section headers
- Badges & counts: Show status badges and notification counts inline
- Active indicator: Bg fill, icon color, and trailing dot
- User profile footer: Avatar, name, and email anchored to the bottom
- Custom logo slot: Brand identity in the header
- Tooltip on collapse: Labels appear as native tooltips when collapsed
- Dark mode: Full dark mode support via semantic tokens
Accessibility
Accessibility considerations
ARIA Attributes
Uses <aside> element for semantic structurerole="navigation" for the nav containeraria-current="page" on the active itemaria-label on the collapse toggle describes the actionKeyboard Navigation
| Key | Action |
|---|---|
| Tab | Navigate between items |
| Enter / Space | Activate item or toggle collapse |
Notes
- Collapsed state uses native title tooltips to preserve labels
- Focus visible on all interactive elements
- Icons include accessible labels via title attribute when collapsed