Eidetic

Vertical Sidebar

Navigation
Layout

Side navigation with collapsible layout, sectioned items, badges, counts, and a user profile footer.

Preview

Sidebar in context — a realistic 3-column application shell

eidetic.io/dashboard

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

Sections

Compact

Collapsed

Minimal

No headers

Anatomy

The building blocks that make up a vertical sidebar

1

Header

Logo, brand name, and optional collapse toggle

2

Nav sections

Grouped items with uppercase section labels

3

Item

Icon, label, optional badge or count, active indicator

4

User footer

Avatar, name, email — anchored to the bottom

Props

Component API reference

PropTypeDefaultDescription
items*NavItem[]Main navigation items
secondaryItemsNavItem[]Secondary navigation items
activeItemstringCurrently active item id
onSelect(id: string) => voidItem select callback
collapsedbooleanfalseCollapsed (icon-only) state
onCollapsedChange(collapsed: boolean) => voidCollapse toggle callback
userUserInfoUser info for footer section
logoReactNodeCustom logo component
variant'default' | 'compact' | 'minimal''default'Visual variant
classNamestringAdditional 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 components

This 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 action

Keyboard Navigation

KeyAction
TabNavigate between items
Enter / SpaceActivate 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