mdxui

Sidebar

Navigation sidebar component for app navigation

Sidebar

The Sidebar component provides the primary navigation for authenticated applications. It displays navigation items, branding, user info, and collapse controls.

Type Signature

interface SidebarProps {
  /** Navigation items */
  nav: NavItem[]
  /** User info for bottom of sidebar */
  user?: {
    name: string
    email: string
    avatar?: string
  }
  /** Branding */
  logo?: React.ReactNode
  /** Collapsed state */
  collapsed?: boolean
  /** On collapse toggle */
  onCollapse?: () => void
}

interface NavItem {
  label: string
  href: string
  icon?: string
  description?: string
  children?: NavItem[]
}

Usage

const nav = [
  { label: 'Dashboard', href: '/', icon: 'LayoutDashboard' },
  { label: 'API Keys', href: '/keys', icon: 'Key' },
  { label: 'Webhooks', href: '/webhooks', icon: 'Webhook' },
  { label: 'Settings', href: '/settings', icon: 'Settings' },
]

<Sidebar
  nav={nav}
  user={{
    name: 'John Doe',
    email: 'john@acme.com',
    avatar: 'https://...'
  }}
/>

Props

Array of navigation items to display. Supports nested items for section grouping.

const nav = [
  {
    label: 'Dashboard',
    href: '/',
    icon: 'LayoutDashboard'
  },
  {
    label: 'Developer',
    href: '/developer',
    icon: 'Code',
    children: [
      { label: 'API Keys', href: '/keys', icon: 'Key' },
      { label: 'Webhooks', href: '/webhooks', icon: 'Webhook' },
      { label: 'Logs', href: '/logs', icon: 'FileText' },
    ]
  },
  {
    label: 'Settings',
    href: '/settings',
    icon: 'Settings'
  }
]

user

User information displayed at the bottom of the sidebar.

<Sidebar
  nav={nav}
  user={{
    name: 'John Doe',
    email: 'john@acme.com',
    avatar: 'https://avatar.example.com/john.jpg'
  }}
/>

Without avatar:

<Sidebar
  nav={nav}
  user={{
    name: 'John Doe',
    email: 'john@acme.com'
    // Fallback to initials (JD)
  }}
/>

Custom branding element displayed at the top of the sidebar.

<Sidebar
  nav={nav}
  logo={
    <img src="/logo.svg" alt="Acme" />
  }
/>

Or use text:

<Sidebar
  nav={nav}
  logo={
    <span className="font-bold text-lg">Acme</span>
  }
/>

collapsed

Controls the collapsed state. When true, shows icons only.

<Sidebar
  nav={nav}
  collapsed={true}
/>

onCollapse

Callback when the collapse toggle is clicked.

<Sidebar
  nav={nav}
  collapsed={isCollapsed}
  onCollapse={() => setIsCollapsed(!isCollapsed)}
/>

Flat Navigation

Simple list of top-level items:

const nav = [
  { label: 'Dashboard', href: '/', icon: 'LayoutDashboard' },
  { label: 'Projects', href: '/projects', icon: 'Folder' },
  { label: 'Team', href: '/team', icon: 'Users' },
  { label: 'Settings', href: '/settings', icon: 'Settings' },
]

Grouped Navigation

Items organized into collapsible sections:

const nav = [
  { label: 'Dashboard', href: '/', icon: 'LayoutDashboard' },
  {
    label: 'Management',
    href: '/manage',
    icon: 'FolderOpen',
    children: [
      { label: 'Projects', href: '/projects', icon: 'Folder' },
      { label: 'Team', href: '/team', icon: 'Users' },
      { label: 'Clients', href: '/clients', icon: 'Building' },
    ]
  },
  {
    label: 'Developer',
    href: '/dev',
    icon: 'Code',
    children: [
      { label: 'API Keys', href: '/keys', icon: 'Key' },
      { label: 'Webhooks', href: '/webhooks', icon: 'Webhook' },
    ]
  },
  { label: 'Settings', href: '/settings', icon: 'Settings' },
]

Icon-Only (Collapsed)

When collapsed, only icons are visible:

┌───┐
│ □ │  Dashboard
│ 📁│  Projects
│ 👥│  Team
│ ⚙│  Settings
└───┘

Expanded with Labels

When expanded, icons + labels + descriptions:

┌──────────────────┐
│ □  Dashboard     │
│    Overview      │
│                  │
│ 📁 Projects      │
│    View all      │
│                  │
│ 👥 Team          │
│    Members       │
│                  │
│ ⚙  Settings      │
│    Configure     │
└──────────────────┘

Common Layouts

Developer App

const nav = [
  { label: 'Overview', href: '/', icon: 'LayoutDashboard' },
  { label: 'API Keys', href: '/keys', icon: 'Key' },
  { label: 'Webhooks', href: '/webhooks', icon: 'Webhook' },
  { label: 'Usage', href: '/usage', icon: 'BarChart' },
  { label: 'Logs', href: '/logs', icon: 'FileText' },
  { label: 'Docs', href: '/docs', icon: 'Book' },
  { label: 'Settings', href: '/settings', icon: 'Settings' },
]

Admin App

const nav = [
  { label: 'Dashboard', href: '/', icon: 'LayoutDashboard' },
  {
    label: 'Collections',
    href: '/collections',
    icon: 'Database',
    children: [
      { label: 'Posts', href: '/posts' },
      { label: 'Pages', href: '/pages' },
      { label: 'Media', href: '/media' },
    ]
  },
  {
    label: 'Access',
    href: '/access',
    icon: 'Shield',
    children: [
      { label: 'Users', href: '/users' },
      { label: 'Roles', href: '/roles' },
    ]
  },
  { label: 'Settings', href: '/settings', icon: 'Settings' },
]

SaaS App

const nav = [
  { label: 'Dashboard', href: '/', icon: 'LayoutDashboard' },
  { label: 'Projects', href: '/projects', icon: 'Folder' },
  { label: 'Team', href: '/team', icon: 'Users' },
  { label: 'Billing', href: '/billing', icon: 'CreditCard' },
  { label: 'Settings', href: '/settings', icon: 'Settings' },
]

CRM App

const nav = [
  { label: 'Dashboard', href: '/', icon: 'LayoutDashboard' },
  { label: 'Contacts', href: '/contacts', icon: 'Users' },
  { label: 'Deals', href: '/deals', icon: 'TrendingUp' },
  { label: 'Activities', href: '/activities', icon: 'Calendar' },
  { label: 'Reports', href: '/reports', icon: 'BarChart' },
  { label: 'Settings', href: '/settings', icon: 'Settings' },
]

Active State

The Sidebar automatically highlights the current route:

// When at /keys, the "API Keys" item is highlighted
<Sidebar
  nav={[
    { label: 'Dashboard', href: '/' },
    { label: 'API Keys', href: '/keys' },  // ← Active
    { label: 'Webhooks', href: '/webhooks' },
  ]}
/>

For nested items, parent items are also highlighted:

// When at /keys, both "Developer" and "API Keys" are highlighted
<Sidebar
  nav={[
    { label: 'Dashboard', href: '/' },
    {
      label: 'Developer',          // ← Parent active
      href: '/developer',
      children: [
        { label: 'API Keys', href: '/keys' },  // ← Active
        { label: 'Webhooks', href: '/webhooks' },
      ]
    },
  ]}
/>

Icons

The Sidebar uses Lucide icon names. Common icons:

Icon NameUse Case
LayoutDashboardDashboard/overview
FolderProjects/collections
UsersTeam/contacts
KeyAPI keys
WebhookWebhooks
BarChartAnalytics/usage
FileTextLogs/documents
SettingsSettings
CreditCardBilling
ShieldSecurity/access
CodeDeveloper tools
DatabaseData/collections
BellNotifications
CalendarSchedule/events

See Lucide Icons for the complete list.

User Menu

The user section at the bottom provides:

  • Profile - Name, email, avatar
  • Account menu - Dropdown with actions
  • Status indicator - Online/offline state
<Sidebar
  nav={nav}
  user={{
    name: 'John Doe',
    email: 'john@acme.com',
    avatar: 'https://...'
  }}
/>

The user menu includes:

  • Profile
  • Settings
  • Billing (if applicable)
  • Help & Support
  • Sign Out

Responsive Behavior

Desktop (≥1024px)

Full sidebar with labels:

┌────────────────┐
│ Logo           │
├────────────────┤
│ □  Dashboard   │
│ 📁 Projects    │
│ 👥 Team        │
│ ⚙  Settings    │
├────────────────┤
│ 👤 John Doe    │
└────────────────┘

Tablet (768px - 1023px)

Collapsed by default (icons only):

┌───┐
│ ≡ │
├───┤
│ □ │
│ 📁│
│ 👥│
│ ⚙ │
├───┤
│ 👤│
└───┘

Mobile (under 768px)

Hidden by default, slides over as drawer:

┌──────────────────────┐
│ ☰ Menu          ✕    │
│                      │
│ □  Dashboard         │
│ 📁 Projects          │
│ 👥 Team              │
│ ⚙  Settings          │
│                      │
│                      │
│ 👤 John Doe          │
└──────────────────────┘

Customization

Custom Width

Override the default width (240px):

<Sidebar
  className="w-64"  // 256px
  nav={nav}
/>

Custom Styling

Apply custom styles:

<Sidebar
  className="bg-slate-900 text-white"
  nav={nav}
/>

Custom Logo Size

<Sidebar
  logo={
    <img src="/logo.svg" className="h-8" alt="Acme" />
  }
  nav={nav}
/>

Accessibility

The Sidebar implements accessibility best practices:

  • Semantic HTML - Uses <nav> element
  • ARIA labels - Descriptive labels for screen readers
  • Keyboard navigation - Arrow keys to navigate items
  • Focus management - Visible focus indicators
  • Collapse state - Announced to screen readers
<nav role="navigation" aria-label="Main navigation">
  <button aria-expanded="false" aria-label="Expand sidebar">
    {/* Collapse toggle */}
  </button>
  <ul role="list">
    <li>
      <a href="/" aria-current="page">Dashboard</a>
    </li>
    {/* ... */}
  </ul>
</nav>

Best Practices

Keep Navigation Flat

Avoid deep nesting (max 2 levels):

// Good - 2 levels
const nav = [
  { label: 'Dashboard', href: '/' },
  {
    label: 'Developer',
    children: [
      { label: 'API Keys', href: '/keys' },
      { label: 'Webhooks', href: '/webhooks' },
    ]
  },
]

// Bad - 3+ levels
const nav = [
  {
    label: 'Developer',
    children: [
      {
        label: 'API',
        children: [  // Too deep!
          { label: 'Keys', href: '/keys' },
        ]
      }
    ]
  }
]

Use Consistent Icons

Choose icons that clearly represent their function:

// Good - clear icons
{ label: 'Settings', icon: 'Settings' }
{ label: 'Team', icon: 'Users' }
{ label: 'Dashboard', icon: 'LayoutDashboard' }

// Bad - confusing icons
{ label: 'Settings', icon: 'Cloud' }  // Unclear
{ label: 'Team', icon: 'Star' }      // Unclear

Limit Items

Keep navigation focused (5-10 top-level items):

// Good - focused navigation
const nav = [
  { label: 'Dashboard', href: '/' },
  { label: 'Projects', href: '/projects' },
  { label: 'Team', href: '/team' },
  { label: 'Settings', href: '/settings' },
]

// Bad - too many items
const nav = [
  { label: 'Dashboard', href: '/' },
  { label: 'Projects', href: '/projects' },
  { label: 'Tasks', href: '/tasks' },
  { label: 'Files', href: '/files' },
  { label: 'Messages', href: '/messages' },
  { label: 'Calendar', href: '/calendar' },
  { label: 'Team', href: '/team' },
  { label: 'Clients', href: '/clients' },
  { label: 'Invoices', href: '/invoices' },
  { label: 'Reports', href: '/reports' },
  { label: 'Settings', href: '/settings' },
  // Too many!
]

On this page