8 CSS Navbar Designs04 / 08
Vertical CSS Sidebar Navigation
A GitHub-dark-inspired collapsible sidebar navbar UI for a SaaS dashboard — proving that the canonical 240px ↔ 64px sidebar collapse pattern can carry a complete information density. Sidebar with gradient hex logo, a circular collapse-toggle button that rotates 180° on click, a workspace selector card (Acme Corp / Pro Plan), three nav sections (Overview / Workspace / System) with mono-uppercase labels and colour-coded badges (Live green, "12" blue, "2" orange, "3" red), and a bottom user row with gradient avatar. On collapse the entire 240px width animates to 64px — every label, badge, and the workspace info smoothly fade out — and tooltips appear on hover via a `data-label` attribute. The main pane carries a sticky topbar (breadcrumb / ⌘K search / notifications dot / command icon) and the actual dashboard content: 4-up stat cards (Revenue $84.2k +12.4%, Active Users 4,291, Deployments 138 −3.2%, Uptime 99.97%) plus a 14-bar Request Volume chart + Recent Activity feed. IBM Plex Sans + IBM Plex Mono. Best for SaaS admin panels, developer tools, internal dashboards, analytics platforms, B2B product chrome.
Published Updated
This is a full-page demo — interact inside the frame above, or open it in the playground for the full-screen experience.
The code
<section class="nb-sdb" aria-label="hexlane collapsible sidebar demo">
<aside data-nb-sdb-sidebar aria-label="Primary">
<div class="sidebar-logo">
<div class="logo-icon" aria-hidden="true">⬡</div>
<span class="logo-text">hexlane<span class="logo-dot">.</span>io</span>
</div>
<div class="workspace">
<div class="ws-avatar">A</div>
<div class="ws-info">
<div class="ws-name">Acme Corp</div>
<div class="ws-plan">Pro Plan</div>
</div>
<span class="ws-chevron" aria-hidden="true"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="6 9 12 15 18 9"/></svg></span>
</div>
<nav class="sidebar-nav" aria-label="Sections">
<div class="nav-section">
<div class="nav-section-label">Overview</div>
<a href="#" class="nav-item active" data-label="Dashboard">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg></span>
<span class="nav-label">Dashboard</span>
</a>
<a href="#" class="nav-item" data-label="Analytics">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg></span>
<span class="nav-label">Analytics</span>
<span class="nav-badge badge-green">Live</span>
</a>
<a href="#" class="nav-item" data-label="Reports">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14,2 14,8 20,8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg></span>
<span class="nav-label">Reports</span>
</a>
</div>
<div class="nav-section">
<div class="nav-section-label">Workspace</div>
<a href="#" class="nav-item" data-label="Projects">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><polygon points="12,2 2,7 12,12 22,7"/><polyline points="2,17 12,22 22,17"/><polyline points="2,12 12,17 22,12"/></svg></span>
<span class="nav-label">Projects</span>
<span class="nav-badge badge-blue">12</span>
</a>
<a href="#" class="nav-item" data-label="Team">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg></span>
<span class="nav-label">Team</span>
</a>
<a href="#" class="nav-item" data-label="Deployments">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><polyline points="22,12 18,12 15,21 9,3 6,12 2,12"/></svg></span>
<span class="nav-label">Deployments</span>
<span class="nav-badge badge-orange">2</span>
</a>
<a href="#" class="nav-item" data-label="Logs">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg></span>
<span class="nav-label">Logs</span>
</a>
</div>
<div class="nav-section">
<div class="nav-section-label">System</div>
<a href="#" class="nav-item" data-label="Alerts">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg></span>
<span class="nav-label">Alerts</span>
<span class="nav-badge badge-red">3</span>
</a>
<a href="#" class="nav-item" data-label="Settings">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg></span>
<span class="nav-label">Settings</span>
</a>
<a href="#" class="nav-item" data-label="Docs">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg></span>
<span class="nav-label">Docs</span>
</a>
</div>
</nav>
<div class="sidebar-foot">
<div class="user-row">
<div class="user-avatar">JL</div>
<div class="user-info">
<div class="user-name">Jordan Lee</div>
<div class="user-handle">admin · Acme Corp</div>
</div>
<span class="user-menu-btn" aria-hidden="true"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="5" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="12" cy="19" r="1"/></svg></span>
</div>
</div>
</aside>
<button class="collapse-btn" type="button" data-nb-sdb-toggle aria-label="Toggle sidebar" aria-expanded="true">
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="15 18 9 12 15 6"/></svg>
</button>
<div class="main">
<div class="topbar">
<div class="breadcrumb">
<span>hexlane</span>
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="9 18 15 12 9 6"/></svg>
<span>Acme Corp</span>
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="9 18 15 12 9 6"/></svg>
<strong>Dashboard</strong>
</div>
<div class="topbar-spacer"></div>
<div class="topbar-search">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
Search...
<span class="search-shortcut">⌘K</span>
</div>
<div class="topbar-actions">
<button class="topbar-icon" type="button" aria-label="Notifications">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg>
<span class="notif-dot" aria-hidden="true"></span>
</button>
<button class="topbar-icon" type="button" aria-label="Command palette">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/></svg>
</button>
</div>
</div>
<div class="content">
<h1 class="page-title">Overview</h1>
<p class="page-desc">Your workspace at a glance — updated just now</p>
<div class="stats-row">
<div class="stat-card">
<div class="stat-label">Monthly Revenue</div>
<div class="stat-value">$84.2k</div>
<div class="stat-change up"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="18 15 12 9 6 15"/></svg> +12.4%</div>
</div>
<div class="stat-card">
<div class="stat-label">Active Users</div>
<div class="stat-value">4,291</div>
<div class="stat-change up"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="18 15 12 9 6 15"/></svg> +8.1%</div>
</div>
<div class="stat-card">
<div class="stat-label">Deployments</div>
<div class="stat-value">138</div>
<div class="stat-change down"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="6 9 12 15 18 9"/></svg> −3.2%</div>
</div>
<div class="stat-card">
<div class="stat-label">Uptime SLA</div>
<div class="stat-value">99.97%</div>
<div class="stat-change up"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="18 15 12 9 6 15"/></svg> Stable</div>
</div>
</div>
<div class="chart-area">
<div class="chart-card">
<div class="chart-title">Request Volume</div>
<div class="chart-sub">Last 14 days — hover over bars</div>
<div class="chart-bars" aria-hidden="true">
<div class="bar bh-45"></div><div class="bar bh-60"></div><div class="bar bh-40"></div><div class="bar bh-70"></div><div class="bar bh-55"></div><div class="bar bh-80"></div><div class="bar active bh-90"></div><div class="bar bh-65"></div><div class="bar bh-75"></div><div class="bar bh-50"></div><div class="bar bh-85"></div><div class="bar bh-70"></div><div class="bar bh-95"></div><div class="bar bh-78"></div>
</div>
</div>
<div class="chart-card">
<div class="chart-title">Recent Activity</div>
<div class="chart-sub">Live feed</div>
<div class="activity-list">
<div class="activity-item">
<div class="activity-dot dot-green" aria-hidden="true"></div>
<div class="activity-text"><strong>Deploy succeeded</strong> — production v2.4.1</div>
<div class="activity-time">2m ago</div>
</div>
<div class="activity-item">
<div class="activity-dot dot-blue" aria-hidden="true"></div>
<div class="activity-text"><strong>Jordan Lee</strong> updated API keys</div>
<div class="activity-time">14m</div>
</div>
<div class="activity-item">
<div class="activity-dot dot-orange" aria-hidden="true"></div>
<div class="activity-text"><strong>Alert triggered</strong> — latency spike</div>
<div class="activity-time">1h</div>
</div>
<div class="activity-item">
<div class="activity-dot dot-red" aria-hidden="true"></div>
<div class="activity-text"><strong>Build failed</strong> — staging branch</div>
<div class="activity-time">2h</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section><section class="nb-sdb" aria-label="hexlane collapsible sidebar demo">
<aside data-nb-sdb-sidebar aria-label="Primary">
<div class="sidebar-logo">
<div class="logo-icon" aria-hidden="true">⬡</div>
<span class="logo-text">hexlane<span class="logo-dot">.</span>io</span>
</div>
<div class="workspace">
<div class="ws-avatar">A</div>
<div class="ws-info">
<div class="ws-name">Acme Corp</div>
<div class="ws-plan">Pro Plan</div>
</div>
<span class="ws-chevron" aria-hidden="true"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="6 9 12 15 18 9"/></svg></span>
</div>
<nav class="sidebar-nav" aria-label="Sections">
<div class="nav-section">
<div class="nav-section-label">Overview</div>
<a href="#" class="nav-item active" data-label="Dashboard">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg></span>
<span class="nav-label">Dashboard</span>
</a>
<a href="#" class="nav-item" data-label="Analytics">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg></span>
<span class="nav-label">Analytics</span>
<span class="nav-badge badge-green">Live</span>
</a>
<a href="#" class="nav-item" data-label="Reports">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14,2 14,8 20,8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg></span>
<span class="nav-label">Reports</span>
</a>
</div>
<div class="nav-section">
<div class="nav-section-label">Workspace</div>
<a href="#" class="nav-item" data-label="Projects">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><polygon points="12,2 2,7 12,12 22,7"/><polyline points="2,17 12,22 22,17"/><polyline points="2,12 12,17 22,12"/></svg></span>
<span class="nav-label">Projects</span>
<span class="nav-badge badge-blue">12</span>
</a>
<a href="#" class="nav-item" data-label="Team">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg></span>
<span class="nav-label">Team</span>
</a>
<a href="#" class="nav-item" data-label="Deployments">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><polyline points="22,12 18,12 15,21 9,3 6,12 2,12"/></svg></span>
<span class="nav-label">Deployments</span>
<span class="nav-badge badge-orange">2</span>
</a>
<a href="#" class="nav-item" data-label="Logs">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg></span>
<span class="nav-label">Logs</span>
</a>
</div>
<div class="nav-section">
<div class="nav-section-label">System</div>
<a href="#" class="nav-item" data-label="Alerts">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg></span>
<span class="nav-label">Alerts</span>
<span class="nav-badge badge-red">3</span>
</a>
<a href="#" class="nav-item" data-label="Settings">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg></span>
<span class="nav-label">Settings</span>
</a>
<a href="#" class="nav-item" data-label="Docs">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg></span>
<span class="nav-label">Docs</span>
</a>
</div>
</nav>
<div class="sidebar-foot">
<div class="user-row">
<div class="user-avatar">JL</div>
<div class="user-info">
<div class="user-name">Jordan Lee</div>
<div class="user-handle">admin · Acme Corp</div>
</div>
<span class="user-menu-btn" aria-hidden="true"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="5" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="12" cy="19" r="1"/></svg></span>
</div>
</div>
</aside>
<button class="collapse-btn" type="button" data-nb-sdb-toggle aria-label="Toggle sidebar" aria-expanded="true">
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="15 18 9 12 15 6"/></svg>
</button>
<div class="main">
<div class="topbar">
<div class="breadcrumb">
<span>hexlane</span>
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="9 18 15 12 9 6"/></svg>
<span>Acme Corp</span>
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="9 18 15 12 9 6"/></svg>
<strong>Dashboard</strong>
</div>
<div class="topbar-spacer"></div>
<div class="topbar-search">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
Search...
<span class="search-shortcut">⌘K</span>
</div>
<div class="topbar-actions">
<button class="topbar-icon" type="button" aria-label="Notifications">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg>
<span class="notif-dot" aria-hidden="true"></span>
</button>
<button class="topbar-icon" type="button" aria-label="Command palette">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/></svg>
</button>
</div>
</div>
<div class="content">
<h1 class="page-title">Overview</h1>
<p class="page-desc">Your workspace at a glance — updated just now</p>
<div class="stats-row">
<div class="stat-card">
<div class="stat-label">Monthly Revenue</div>
<div class="stat-value">$84.2k</div>
<div class="stat-change up"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="18 15 12 9 6 15"/></svg> +12.4%</div>
</div>
<div class="stat-card">
<div class="stat-label">Active Users</div>
<div class="stat-value">4,291</div>
<div class="stat-change up"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="18 15 12 9 6 15"/></svg> +8.1%</div>
</div>
<div class="stat-card">
<div class="stat-label">Deployments</div>
<div class="stat-value">138</div>
<div class="stat-change down"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="6 9 12 15 18 9"/></svg> −3.2%</div>
</div>
<div class="stat-card">
<div class="stat-label">Uptime SLA</div>
<div class="stat-value">99.97%</div>
<div class="stat-change up"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="18 15 12 9 6 15"/></svg> Stable</div>
</div>
</div>
<div class="chart-area">
<div class="chart-card">
<div class="chart-title">Request Volume</div>
<div class="chart-sub">Last 14 days — hover over bars</div>
<div class="chart-bars" aria-hidden="true">
<div class="bar bh-45"></div><div class="bar bh-60"></div><div class="bar bh-40"></div><div class="bar bh-70"></div><div class="bar bh-55"></div><div class="bar bh-80"></div><div class="bar active bh-90"></div><div class="bar bh-65"></div><div class="bar bh-75"></div><div class="bar bh-50"></div><div class="bar bh-85"></div><div class="bar bh-70"></div><div class="bar bh-95"></div><div class="bar bh-78"></div>
</div>
</div>
<div class="chart-card">
<div class="chart-title">Recent Activity</div>
<div class="chart-sub">Live feed</div>
<div class="activity-list">
<div class="activity-item">
<div class="activity-dot dot-green" aria-hidden="true"></div>
<div class="activity-text"><strong>Deploy succeeded</strong> — production v2.4.1</div>
<div class="activity-time">2m ago</div>
</div>
<div class="activity-item">
<div class="activity-dot dot-blue" aria-hidden="true"></div>
<div class="activity-text"><strong>Jordan Lee</strong> updated API keys</div>
<div class="activity-time">14m</div>
</div>
<div class="activity-item">
<div class="activity-dot dot-orange" aria-hidden="true"></div>
<div class="activity-text"><strong>Alert triggered</strong> — latency spike</div>
<div class="activity-time">1h</div>
</div>
<div class="activity-item">
<div class="activity-dot dot-red" aria-hidden="true"></div>
<div class="activity-text"><strong>Build failed</strong> — staging branch</div>
<div class="activity-time">2h</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>/* ─── 04 hexlane — collapsible sidebar dashboard navbar UI ─────── */
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap');
.nb-sdb {
--nb-sdb-sidebar-w: 240px;
--nb-sdb-sidebar-collapsed: 64px;
--nb-sdb-bg: #0d1117;
--nb-sdb-surface: #161b22;
--nb-sdb-surface-2: #21262d;
--nb-sdb-border: #30363d;
--nb-sdb-text: #e6edf3;
--nb-sdb-text-muted: #7d8590;
--nb-sdb-text-dim: #484f58;
--nb-sdb-accent: #58a6ff;
--nb-sdb-accent-green: #3fb950;
--nb-sdb-accent-orange: #d29922;
--nb-sdb-accent-red: #f85149;
--nb-sdb-accent-purple: #bc8cff;
--nb-sdb-transition: 0.22s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
width: 100%;
min-height: 720px;
background: var(--nb-sdb-bg);
color: var(--nb-sdb-text);
font-family: 'IBM Plex Sans', sans-serif;
display: flex;
overflow: hidden;
box-sizing: border-box;
}
.nb-sdb *,
.nb-sdb *::before,
.nb-sdb *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.nb-sdb aside {
width: var(--nb-sdb-sidebar-w);
background: var(--nb-sdb-surface);
border-right: 1px solid var(--nb-sdb-border);
display: flex;
flex-direction: column;
transition: width var(--nb-sdb-transition);
position: relative;
z-index: 50;
overflow: hidden;
flex-shrink: 0;
}
.nb-sdb aside.collapsed {
width: var(--nb-sdb-sidebar-collapsed);
}
.nb-sdb .sidebar-logo {
display: flex;
align-items: center;
gap: 10px;
padding: 0 16px;
height: 56px;
border-bottom: 1px solid var(--nb-sdb-border);
flex-shrink: 0;
overflow: hidden;
white-space: nowrap;
}
.nb-sdb .logo-icon {
width: 32px;
height: 32px;
border-radius: 8px;
background: linear-gradient(135deg, var(--nb-sdb-accent), var(--nb-sdb-accent-purple));
display: flex;
align-items: center;
justify-content: center;
font-size: 0.9rem;
flex-shrink: 0;
box-shadow: 0 2px 12px rgba(88,166,255,0.3);
color: #fff;
}
.nb-sdb .logo-text {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.9rem;
font-weight: 500;
letter-spacing: -0.02em;
color: var(--nb-sdb-text);
transition: opacity var(--nb-sdb-transition), width var(--nb-sdb-transition);
overflow: hidden;
}
.nb-sdb .logo-dot {
color: var(--nb-sdb-accent);
}
.nb-sdb aside.collapsed .logo-text {
opacity: 0;
width: 0;
}
/* Collapse toggle sits at the sidebar's outer edge. Lifted out of
<aside> so aside's overflow:hidden (which clips the fading labels)
doesn't also clip this button. Positioned absolute against the
wrapper; its left coord tracks the sidebar width via :has(). */
.nb-sdb .collapse-btn {
position: absolute;
top: 68px;
left: calc(var(--nb-sdb-sidebar-w) - 12px);
width: 24px;
height: 24px;
border-radius: 50%;
background: var(--nb-sdb-surface-2);
border: 1px solid var(--nb-sdb-border);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
color: var(--nb-sdb-text-muted);
transition: background 0.15s, color 0.15s, left var(--nb-sdb-transition);
z-index: 60;
}
.nb-sdb:has(aside.collapsed) .collapse-btn {
left: calc(var(--nb-sdb-sidebar-collapsed) - 12px);
}
.nb-sdb .collapse-btn:hover {
background: var(--nb-sdb-accent);
color: #fff;
border-color: var(--nb-sdb-accent);
}
.nb-sdb .collapse-btn svg {
transition: transform var(--nb-sdb-transition);
}
.nb-sdb:has(aside.collapsed) .collapse-btn svg {
transform: rotate(180deg);
}
.nb-sdb .workspace {
margin: 12px 10px;
padding: 8px 10px;
border-radius: 8px;
border: 1px solid var(--nb-sdb-border);
background: var(--nb-sdb-surface-2);
display: flex;
align-items: center;
gap: 10px;
cursor: pointer;
transition: border-color 0.15s, background 0.15s;
overflow: hidden;
white-space: nowrap;
flex-shrink: 0;
}
.nb-sdb .workspace:hover {
border-color: var(--nb-sdb-accent);
background: rgba(88,166,255,0.05);
}
.nb-sdb .ws-avatar {
width: 24px;
height: 24px;
border-radius: 6px;
background: linear-gradient(135deg, #3fb950, #1f6feb);
flex-shrink: 0;
font-size: 0.6rem;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-weight: 600;
}
.nb-sdb .ws-info {
flex: 1;
min-width: 0;
overflow: hidden;
transition: opacity var(--nb-sdb-transition), width var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .ws-info {
opacity: 0;
width: 0;
}
.nb-sdb .ws-name {
font-size: 0.75rem;
font-weight: 500;
color: var(--nb-sdb-text);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.nb-sdb .ws-plan {
font-size: 0.6rem;
color: var(--nb-sdb-text-muted);
letter-spacing: 0.05em;
text-transform: uppercase;
}
.nb-sdb .ws-chevron {
color: var(--nb-sdb-text-dim);
flex-shrink: 0;
transition: opacity var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .ws-chevron {
opacity: 0;
}
.nb-sdb .sidebar-nav {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
padding: 8px 0;
scrollbar-width: thin;
scrollbar-color: var(--nb-sdb-border) transparent;
}
.nb-sdb .sidebar-nav::-webkit-scrollbar {
width: 4px;
}
.nb-sdb .sidebar-nav::-webkit-scrollbar-thumb {
background: var(--nb-sdb-border);
border-radius: 2px;
}
.nb-sdb .nav-section {
margin-bottom: 4px;
}
.nb-sdb .nav-section-label {
font-size: 0.6rem;
font-weight: 600;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--nb-sdb-text-dim);
padding: 8px 20px 4px;
white-space: nowrap;
overflow: hidden;
transition: opacity var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .nav-section-label {
opacity: 0;
}
.nb-sdb .nav-item {
position: relative;
display: flex;
align-items: center;
gap: 10px;
padding: 7px 10px 7px 16px;
margin: 1px 8px;
border-radius: 8px;
font-size: 0.82rem;
font-weight: 400;
color: var(--nb-sdb-text-muted);
text-decoration: none;
cursor: pointer;
transition: background 0.12s, color 0.12s;
white-space: nowrap;
overflow: hidden;
user-select: none;
}
.nb-sdb .nav-item:hover {
background: var(--nb-sdb-surface-2);
color: var(--nb-sdb-text);
}
.nb-sdb .nav-item.active {
background: rgba(88,166,255,0.1);
color: var(--nb-sdb-accent);
}
.nb-sdb .nav-item.active::before {
content: '';
position: absolute;
left: 0;
top: 20%;
bottom: 20%;
width: 3px;
border-radius: 0 2px 2px 0;
background: var(--nb-sdb-accent);
}
.nb-sdb .nav-icon {
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
opacity: 0.8;
}
.nb-sdb .nav-item.active .nav-icon,
.nb-sdb .nav-item:hover .nav-icon {
opacity: 1;
}
.nb-sdb .nav-label {
transition: opacity var(--nb-sdb-transition), width var(--nb-sdb-transition);
overflow: hidden;
}
.nb-sdb aside.collapsed .nav-label {
opacity: 0;
width: 0;
}
.nb-sdb .nav-badge {
margin-left: auto;
flex-shrink: 0;
font-size: 0.6rem;
font-weight: 600;
padding: 2px 6px;
border-radius: 100px;
transition: opacity var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .nav-badge {
opacity: 0;
}
.nb-sdb .badge-blue {
background: rgba(88,166,255,0.15);
color: var(--nb-sdb-accent);
}
.nb-sdb .badge-green {
background: rgba(63,185,80,0.15);
color: var(--nb-sdb-accent-green);
}
.nb-sdb .badge-orange {
background: rgba(210,153,34,0.15);
color: var(--nb-sdb-accent-orange);
}
.nb-sdb .badge-red {
background: rgba(248,81,73,0.15);
color: var(--nb-sdb-accent-red);
}
.nb-sdb aside.collapsed .nav-item::after {
content: attr(data-label);
position: absolute;
left: calc(var(--nb-sdb-sidebar-collapsed) - 8px);
top: 50%;
transform: translateY(-50%);
background: var(--nb-sdb-surface-2);
color: var(--nb-sdb-text);
font-size: 0.75rem;
padding: 5px 10px;
border-radius: 6px;
border: 1px solid var(--nb-sdb-border);
white-space: nowrap;
pointer-events: none;
opacity: 0;
transition: opacity 0.15s;
z-index: 100;
box-shadow: 0 4px 16px rgba(0,0,0,0.4);
}
.nb-sdb aside.collapsed .nav-item:hover::after {
opacity: 1;
}
.nb-sdb .sidebar-foot {
border-top: 1px solid var(--nb-sdb-border);
padding: 10px;
flex-shrink: 0;
overflow: hidden;
}
.nb-sdb .user-row {
display: flex;
align-items: center;
gap: 10px;
padding: 6px 6px;
border-radius: 8px;
cursor: pointer;
transition: background 0.12s;
white-space: nowrap;
overflow: hidden;
}
.nb-sdb .user-row:hover {
background: var(--nb-sdb-surface-2);
}
.nb-sdb .user-avatar {
width: 32px;
height: 32px;
border-radius: 50%;
background: linear-gradient(135deg, var(--nb-sdb-accent-purple), var(--nb-sdb-accent));
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.75rem;
font-weight: 600;
color: #fff;
}
.nb-sdb .user-info {
flex: 1;
min-width: 0;
overflow: hidden;
transition: opacity var(--nb-sdb-transition), width var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .user-info {
opacity: 0;
width: 0;
}
.nb-sdb .user-name {
font-size: 0.78rem;
font-weight: 500;
color: var(--nb-sdb-text);
overflow: hidden;
text-overflow: ellipsis;
}
.nb-sdb .user-handle {
font-size: 0.65rem;
color: var(--nb-sdb-text-dim);
overflow: hidden;
text-overflow: ellipsis;
}
.nb-sdb .user-menu-btn {
color: var(--nb-sdb-text-dim);
flex-shrink: 0;
transition: opacity var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .user-menu-btn {
opacity: 0;
}
.nb-sdb .main {
flex: 1;
display: flex;
flex-direction: column;
min-height: 720px;
}
.nb-sdb .topbar {
height: 56px;
border-bottom: 1px solid var(--nb-sdb-border);
display: flex;
align-items: center;
padding: 0 24px;
gap: 16px;
background: var(--nb-sdb-surface);
flex-shrink: 0;
}
.nb-sdb .breadcrumb {
display: flex;
align-items: center;
gap: 6px;
font-family: 'IBM Plex Mono', monospace;
font-size: 0.72rem;
color: var(--nb-sdb-text-muted);
}
.nb-sdb .breadcrumb span {
color: var(--nb-sdb-text-dim);
}
.nb-sdb .breadcrumb strong {
color: var(--nb-sdb-text);
font-weight: 500;
}
.nb-sdb .topbar-spacer {
flex: 1;
}
.nb-sdb .topbar-search {
display: flex;
align-items: center;
gap: 8px;
background: var(--nb-sdb-bg);
border: 1px solid var(--nb-sdb-border);
border-radius: 8px;
padding: 6px 12px;
color: var(--nb-sdb-text-muted);
font-size: 0.75rem;
cursor: pointer;
transition: border-color 0.15s;
}
.nb-sdb .topbar-search:hover {
border-color: var(--nb-sdb-text-dim);
}
.nb-sdb .search-shortcut {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.6rem;
background: var(--nb-sdb-surface-2);
border: 1px solid var(--nb-sdb-border);
border-radius: 4px;
padding: 1px 5px;
color: var(--nb-sdb-text-dim);
margin-left: 24px;
}
.nb-sdb .topbar-actions {
display: flex;
align-items: center;
gap: 8px;
}
.nb-sdb .topbar-icon {
width: 32px;
height: 32px;
border-radius: 6px;
border: 1px solid var(--nb-sdb-border);
background: transparent;
display: flex;
align-items: center;
justify-content: center;
color: var(--nb-sdb-text-muted);
cursor: pointer;
transition: background 0.12s, color 0.12s;
position: relative;
}
.nb-sdb .topbar-icon:hover {
background: var(--nb-sdb-surface-2);
color: var(--nb-sdb-text);
}
.nb-sdb .notif-dot {
position: absolute;
top: 6px;
right: 6px;
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--nb-sdb-accent-red);
border: 1.5px solid var(--nb-sdb-surface);
}
.nb-sdb .content {
padding: 28px;
flex: 1;
}
.nb-sdb .page-title {
font-size: 1.2rem;
font-weight: 600;
color: var(--nb-sdb-text);
margin-bottom: 4px;
}
.nb-sdb .page-desc {
font-size: 0.82rem;
color: var(--nb-sdb-text-muted);
margin-bottom: 24px;
}
.nb-sdb .stats-row {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
margin-bottom: 24px;
}
.nb-sdb .stat-card {
background: var(--nb-sdb-surface);
border: 1px solid var(--nb-sdb-border);
border-radius: 12px;
padding: 18px 20px;
transition: border-color 0.15s;
}
.nb-sdb .stat-card:hover {
border-color: var(--nb-sdb-text-dim);
}
.nb-sdb .stat-label {
font-size: 0.7rem;
font-weight: 500;
letter-spacing: 0.05em;
text-transform: uppercase;
color: var(--nb-sdb-text-muted);
margin-bottom: 10px;
}
.nb-sdb .stat-value {
font-family: 'IBM Plex Mono', monospace;
font-size: 1.6rem;
font-weight: 500;
color: var(--nb-sdb-text);
line-height: 1;
margin-bottom: 8px;
}
.nb-sdb .stat-change {
font-size: 0.72rem;
display: flex;
align-items: center;
gap: 4px;
}
.nb-sdb .up {
color: var(--nb-sdb-accent-green);
}
.nb-sdb .down {
color: var(--nb-sdb-accent-red);
}
.nb-sdb .chart-area {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 16px;
}
.nb-sdb .chart-card {
background: var(--nb-sdb-surface);
border: 1px solid var(--nb-sdb-border);
border-radius: 12px;
padding: 20px;
}
.nb-sdb .chart-title {
font-size: 0.82rem;
font-weight: 500;
color: var(--nb-sdb-text);
margin-bottom: 4px;
}
.nb-sdb .chart-sub {
font-size: 0.72rem;
color: var(--nb-sdb-text-muted);
margin-bottom: 16px;
}
.nb-sdb .chart-bars {
display: flex;
align-items: flex-end;
gap: 6px;
height: 100px;
}
.nb-sdb .bar {
flex: 1;
border-radius: 4px 4px 0 0;
background: rgba(88,166,255,0.15);
border: 1px solid rgba(88,166,255,0.2);
transition: background 0.15s;
}
.nb-sdb .bar:hover {
background: rgba(88,166,255,0.35);
}
.nb-sdb .bar.active {
background: rgba(88,166,255,0.6);
border-color: var(--nb-sdb-accent);
}
.nb-sdb .bh-40 {
height: 40%;
}
.nb-sdb .bh-45 {
height: 45%;
}
.nb-sdb .bh-50 {
height: 50%;
}
.nb-sdb .bh-55 {
height: 55%;
}
.nb-sdb .bh-60 {
height: 60%;
}
.nb-sdb .bh-65 {
height: 65%;
}
.nb-sdb .bh-70 {
height: 70%;
}
.nb-sdb .bh-75 {
height: 75%;
}
.nb-sdb .bh-78 {
height: 78%;
}
.nb-sdb .bh-80 {
height: 80%;
}
.nb-sdb .bh-85 {
height: 85%;
}
.nb-sdb .bh-90 {
height: 90%;
}
.nb-sdb .bh-95 {
height: 95%;
}
.nb-sdb .activity-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.nb-sdb .activity-item {
display: flex;
gap: 10px;
align-items: flex-start;
}
.nb-sdb .activity-dot {
width: 8px;
height: 8px;
border-radius: 50%;
flex-shrink: 0;
margin-top: 4px;
}
.nb-sdb .dot-green {
background: var(--nb-sdb-accent-green);
}
.nb-sdb .dot-blue {
background: var(--nb-sdb-accent);
}
.nb-sdb .dot-orange {
background: var(--nb-sdb-accent-orange);
}
.nb-sdb .dot-red {
background: var(--nb-sdb-accent-red);
}
.nb-sdb .activity-text {
font-size: 0.75rem;
line-height: 1.5;
color: var(--nb-sdb-text-muted);
}
.nb-sdb .activity-text strong {
color: var(--nb-sdb-text);
}
.nb-sdb .activity-time {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.65rem;
color: var(--nb-sdb-text-dim);
margin-left: auto;
flex-shrink: 0;
}
@media (max-width: 1024px) {
.nb-sdb .stats-row {
grid-template-columns: repeat(2, 1fr);
}
.nb-sdb .chart-area {
grid-template-columns: 1fr;
}
}
@media (max-width: 640px) {
.nb-sdb .stats-row {
grid-template-columns: 1fr;
}
.nb-sdb .search-shortcut {
display: none;
}
}
@media (prefers-reduced-motion: reduce) {
.nb-sdb aside,
.nb-sdb .nav-label,
.nb-sdb .ws-info,
.nb-sdb .user-info,
.nb-sdb .collapse-btn svg {
transition: none !important;
}
}/* ─── 04 hexlane — collapsible sidebar dashboard navbar UI ─────── */
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap');
.nb-sdb {
--nb-sdb-sidebar-w: 240px;
--nb-sdb-sidebar-collapsed: 64px;
--nb-sdb-bg: #0d1117;
--nb-sdb-surface: #161b22;
--nb-sdb-surface-2: #21262d;
--nb-sdb-border: #30363d;
--nb-sdb-text: #e6edf3;
--nb-sdb-text-muted: #7d8590;
--nb-sdb-text-dim: #484f58;
--nb-sdb-accent: #58a6ff;
--nb-sdb-accent-green: #3fb950;
--nb-sdb-accent-orange: #d29922;
--nb-sdb-accent-red: #f85149;
--nb-sdb-accent-purple: #bc8cff;
--nb-sdb-transition: 0.22s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
width: 100%;
min-height: 720px;
background: var(--nb-sdb-bg);
color: var(--nb-sdb-text);
font-family: 'IBM Plex Sans', sans-serif;
display: flex;
overflow: hidden;
box-sizing: border-box;
}
.nb-sdb *,
.nb-sdb *::before,
.nb-sdb *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.nb-sdb aside {
width: var(--nb-sdb-sidebar-w);
background: var(--nb-sdb-surface);
border-right: 1px solid var(--nb-sdb-border);
display: flex;
flex-direction: column;
transition: width var(--nb-sdb-transition);
position: relative;
z-index: 50;
overflow: hidden;
flex-shrink: 0;
}
.nb-sdb aside.collapsed {
width: var(--nb-sdb-sidebar-collapsed);
}
.nb-sdb .sidebar-logo {
display: flex;
align-items: center;
gap: 10px;
padding: 0 16px;
height: 56px;
border-bottom: 1px solid var(--nb-sdb-border);
flex-shrink: 0;
overflow: hidden;
white-space: nowrap;
}
.nb-sdb .logo-icon {
width: 32px;
height: 32px;
border-radius: 8px;
background: linear-gradient(135deg, var(--nb-sdb-accent), var(--nb-sdb-accent-purple));
display: flex;
align-items: center;
justify-content: center;
font-size: 0.9rem;
flex-shrink: 0;
box-shadow: 0 2px 12px rgba(88,166,255,0.3);
color: #fff;
}
.nb-sdb .logo-text {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.9rem;
font-weight: 500;
letter-spacing: -0.02em;
color: var(--nb-sdb-text);
transition: opacity var(--nb-sdb-transition), width var(--nb-sdb-transition);
overflow: hidden;
}
.nb-sdb .logo-dot {
color: var(--nb-sdb-accent);
}
.nb-sdb aside.collapsed .logo-text {
opacity: 0;
width: 0;
}
/* Collapse toggle sits at the sidebar's outer edge. Lifted out of
<aside> so aside's overflow:hidden (which clips the fading labels)
doesn't also clip this button. Positioned absolute against the
wrapper; its left coord tracks the sidebar width via :has(). */
.nb-sdb .collapse-btn {
position: absolute;
top: 68px;
left: calc(var(--nb-sdb-sidebar-w) - 12px);
width: 24px;
height: 24px;
border-radius: 50%;
background: var(--nb-sdb-surface-2);
border: 1px solid var(--nb-sdb-border);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
color: var(--nb-sdb-text-muted);
transition: background 0.15s, color 0.15s, left var(--nb-sdb-transition);
z-index: 60;
}
.nb-sdb:has(aside.collapsed) .collapse-btn {
left: calc(var(--nb-sdb-sidebar-collapsed) - 12px);
}
.nb-sdb .collapse-btn:hover {
background: var(--nb-sdb-accent);
color: #fff;
border-color: var(--nb-sdb-accent);
}
.nb-sdb .collapse-btn svg {
transition: transform var(--nb-sdb-transition);
}
.nb-sdb:has(aside.collapsed) .collapse-btn svg {
transform: rotate(180deg);
}
.nb-sdb .workspace {
margin: 12px 10px;
padding: 8px 10px;
border-radius: 8px;
border: 1px solid var(--nb-sdb-border);
background: var(--nb-sdb-surface-2);
display: flex;
align-items: center;
gap: 10px;
cursor: pointer;
transition: border-color 0.15s, background 0.15s;
overflow: hidden;
white-space: nowrap;
flex-shrink: 0;
}
.nb-sdb .workspace:hover {
border-color: var(--nb-sdb-accent);
background: rgba(88,166,255,0.05);
}
.nb-sdb .ws-avatar {
width: 24px;
height: 24px;
border-radius: 6px;
background: linear-gradient(135deg, #3fb950, #1f6feb);
flex-shrink: 0;
font-size: 0.6rem;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-weight: 600;
}
.nb-sdb .ws-info {
flex: 1;
min-width: 0;
overflow: hidden;
transition: opacity var(--nb-sdb-transition), width var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .ws-info {
opacity: 0;
width: 0;
}
.nb-sdb .ws-name {
font-size: 0.75rem;
font-weight: 500;
color: var(--nb-sdb-text);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.nb-sdb .ws-plan {
font-size: 0.6rem;
color: var(--nb-sdb-text-muted);
letter-spacing: 0.05em;
text-transform: uppercase;
}
.nb-sdb .ws-chevron {
color: var(--nb-sdb-text-dim);
flex-shrink: 0;
transition: opacity var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .ws-chevron {
opacity: 0;
}
.nb-sdb .sidebar-nav {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
padding: 8px 0;
scrollbar-width: thin;
scrollbar-color: var(--nb-sdb-border) transparent;
}
.nb-sdb .sidebar-nav::-webkit-scrollbar {
width: 4px;
}
.nb-sdb .sidebar-nav::-webkit-scrollbar-thumb {
background: var(--nb-sdb-border);
border-radius: 2px;
}
.nb-sdb .nav-section {
margin-bottom: 4px;
}
.nb-sdb .nav-section-label {
font-size: 0.6rem;
font-weight: 600;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--nb-sdb-text-dim);
padding: 8px 20px 4px;
white-space: nowrap;
overflow: hidden;
transition: opacity var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .nav-section-label {
opacity: 0;
}
.nb-sdb .nav-item {
position: relative;
display: flex;
align-items: center;
gap: 10px;
padding: 7px 10px 7px 16px;
margin: 1px 8px;
border-radius: 8px;
font-size: 0.82rem;
font-weight: 400;
color: var(--nb-sdb-text-muted);
text-decoration: none;
cursor: pointer;
transition: background 0.12s, color 0.12s;
white-space: nowrap;
overflow: hidden;
user-select: none;
}
.nb-sdb .nav-item:hover {
background: var(--nb-sdb-surface-2);
color: var(--nb-sdb-text);
}
.nb-sdb .nav-item.active {
background: rgba(88,166,255,0.1);
color: var(--nb-sdb-accent);
}
.nb-sdb .nav-item.active::before {
content: '';
position: absolute;
left: 0;
top: 20%;
bottom: 20%;
width: 3px;
border-radius: 0 2px 2px 0;
background: var(--nb-sdb-accent);
}
.nb-sdb .nav-icon {
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
opacity: 0.8;
}
.nb-sdb .nav-item.active .nav-icon,
.nb-sdb .nav-item:hover .nav-icon {
opacity: 1;
}
.nb-sdb .nav-label {
transition: opacity var(--nb-sdb-transition), width var(--nb-sdb-transition);
overflow: hidden;
}
.nb-sdb aside.collapsed .nav-label {
opacity: 0;
width: 0;
}
.nb-sdb .nav-badge {
margin-left: auto;
flex-shrink: 0;
font-size: 0.6rem;
font-weight: 600;
padding: 2px 6px;
border-radius: 100px;
transition: opacity var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .nav-badge {
opacity: 0;
}
.nb-sdb .badge-blue {
background: rgba(88,166,255,0.15);
color: var(--nb-sdb-accent);
}
.nb-sdb .badge-green {
background: rgba(63,185,80,0.15);
color: var(--nb-sdb-accent-green);
}
.nb-sdb .badge-orange {
background: rgba(210,153,34,0.15);
color: var(--nb-sdb-accent-orange);
}
.nb-sdb .badge-red {
background: rgba(248,81,73,0.15);
color: var(--nb-sdb-accent-red);
}
.nb-sdb aside.collapsed .nav-item::after {
content: attr(data-label);
position: absolute;
left: calc(var(--nb-sdb-sidebar-collapsed) - 8px);
top: 50%;
transform: translateY(-50%);
background: var(--nb-sdb-surface-2);
color: var(--nb-sdb-text);
font-size: 0.75rem;
padding: 5px 10px;
border-radius: 6px;
border: 1px solid var(--nb-sdb-border);
white-space: nowrap;
pointer-events: none;
opacity: 0;
transition: opacity 0.15s;
z-index: 100;
box-shadow: 0 4px 16px rgba(0,0,0,0.4);
}
.nb-sdb aside.collapsed .nav-item:hover::after {
opacity: 1;
}
.nb-sdb .sidebar-foot {
border-top: 1px solid var(--nb-sdb-border);
padding: 10px;
flex-shrink: 0;
overflow: hidden;
}
.nb-sdb .user-row {
display: flex;
align-items: center;
gap: 10px;
padding: 6px 6px;
border-radius: 8px;
cursor: pointer;
transition: background 0.12s;
white-space: nowrap;
overflow: hidden;
}
.nb-sdb .user-row:hover {
background: var(--nb-sdb-surface-2);
}
.nb-sdb .user-avatar {
width: 32px;
height: 32px;
border-radius: 50%;
background: linear-gradient(135deg, var(--nb-sdb-accent-purple), var(--nb-sdb-accent));
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.75rem;
font-weight: 600;
color: #fff;
}
.nb-sdb .user-info {
flex: 1;
min-width: 0;
overflow: hidden;
transition: opacity var(--nb-sdb-transition), width var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .user-info {
opacity: 0;
width: 0;
}
.nb-sdb .user-name {
font-size: 0.78rem;
font-weight: 500;
color: var(--nb-sdb-text);
overflow: hidden;
text-overflow: ellipsis;
}
.nb-sdb .user-handle {
font-size: 0.65rem;
color: var(--nb-sdb-text-dim);
overflow: hidden;
text-overflow: ellipsis;
}
.nb-sdb .user-menu-btn {
color: var(--nb-sdb-text-dim);
flex-shrink: 0;
transition: opacity var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .user-menu-btn {
opacity: 0;
}
.nb-sdb .main {
flex: 1;
display: flex;
flex-direction: column;
min-height: 720px;
}
.nb-sdb .topbar {
height: 56px;
border-bottom: 1px solid var(--nb-sdb-border);
display: flex;
align-items: center;
padding: 0 24px;
gap: 16px;
background: var(--nb-sdb-surface);
flex-shrink: 0;
}
.nb-sdb .breadcrumb {
display: flex;
align-items: center;
gap: 6px;
font-family: 'IBM Plex Mono', monospace;
font-size: 0.72rem;
color: var(--nb-sdb-text-muted);
}
.nb-sdb .breadcrumb span {
color: var(--nb-sdb-text-dim);
}
.nb-sdb .breadcrumb strong {
color: var(--nb-sdb-text);
font-weight: 500;
}
.nb-sdb .topbar-spacer {
flex: 1;
}
.nb-sdb .topbar-search {
display: flex;
align-items: center;
gap: 8px;
background: var(--nb-sdb-bg);
border: 1px solid var(--nb-sdb-border);
border-radius: 8px;
padding: 6px 12px;
color: var(--nb-sdb-text-muted);
font-size: 0.75rem;
cursor: pointer;
transition: border-color 0.15s;
}
.nb-sdb .topbar-search:hover {
border-color: var(--nb-sdb-text-dim);
}
.nb-sdb .search-shortcut {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.6rem;
background: var(--nb-sdb-surface-2);
border: 1px solid var(--nb-sdb-border);
border-radius: 4px;
padding: 1px 5px;
color: var(--nb-sdb-text-dim);
margin-left: 24px;
}
.nb-sdb .topbar-actions {
display: flex;
align-items: center;
gap: 8px;
}
.nb-sdb .topbar-icon {
width: 32px;
height: 32px;
border-radius: 6px;
border: 1px solid var(--nb-sdb-border);
background: transparent;
display: flex;
align-items: center;
justify-content: center;
color: var(--nb-sdb-text-muted);
cursor: pointer;
transition: background 0.12s, color 0.12s;
position: relative;
}
.nb-sdb .topbar-icon:hover {
background: var(--nb-sdb-surface-2);
color: var(--nb-sdb-text);
}
.nb-sdb .notif-dot {
position: absolute;
top: 6px;
right: 6px;
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--nb-sdb-accent-red);
border: 1.5px solid var(--nb-sdb-surface);
}
.nb-sdb .content {
padding: 28px;
flex: 1;
}
.nb-sdb .page-title {
font-size: 1.2rem;
font-weight: 600;
color: var(--nb-sdb-text);
margin-bottom: 4px;
}
.nb-sdb .page-desc {
font-size: 0.82rem;
color: var(--nb-sdb-text-muted);
margin-bottom: 24px;
}
.nb-sdb .stats-row {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
margin-bottom: 24px;
}
.nb-sdb .stat-card {
background: var(--nb-sdb-surface);
border: 1px solid var(--nb-sdb-border);
border-radius: 12px;
padding: 18px 20px;
transition: border-color 0.15s;
}
.nb-sdb .stat-card:hover {
border-color: var(--nb-sdb-text-dim);
}
.nb-sdb .stat-label {
font-size: 0.7rem;
font-weight: 500;
letter-spacing: 0.05em;
text-transform: uppercase;
color: var(--nb-sdb-text-muted);
margin-bottom: 10px;
}
.nb-sdb .stat-value {
font-family: 'IBM Plex Mono', monospace;
font-size: 1.6rem;
font-weight: 500;
color: var(--nb-sdb-text);
line-height: 1;
margin-bottom: 8px;
}
.nb-sdb .stat-change {
font-size: 0.72rem;
display: flex;
align-items: center;
gap: 4px;
}
.nb-sdb .up {
color: var(--nb-sdb-accent-green);
}
.nb-sdb .down {
color: var(--nb-sdb-accent-red);
}
.nb-sdb .chart-area {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 16px;
}
.nb-sdb .chart-card {
background: var(--nb-sdb-surface);
border: 1px solid var(--nb-sdb-border);
border-radius: 12px;
padding: 20px;
}
.nb-sdb .chart-title {
font-size: 0.82rem;
font-weight: 500;
color: var(--nb-sdb-text);
margin-bottom: 4px;
}
.nb-sdb .chart-sub {
font-size: 0.72rem;
color: var(--nb-sdb-text-muted);
margin-bottom: 16px;
}
.nb-sdb .chart-bars {
display: flex;
align-items: flex-end;
gap: 6px;
height: 100px;
}
.nb-sdb .bar {
flex: 1;
border-radius: 4px 4px 0 0;
background: rgba(88,166,255,0.15);
border: 1px solid rgba(88,166,255,0.2);
transition: background 0.15s;
}
.nb-sdb .bar:hover {
background: rgba(88,166,255,0.35);
}
.nb-sdb .bar.active {
background: rgba(88,166,255,0.6);
border-color: var(--nb-sdb-accent);
}
.nb-sdb .bh-40 {
height: 40%;
}
.nb-sdb .bh-45 {
height: 45%;
}
.nb-sdb .bh-50 {
height: 50%;
}
.nb-sdb .bh-55 {
height: 55%;
}
.nb-sdb .bh-60 {
height: 60%;
}
.nb-sdb .bh-65 {
height: 65%;
}
.nb-sdb .bh-70 {
height: 70%;
}
.nb-sdb .bh-75 {
height: 75%;
}
.nb-sdb .bh-78 {
height: 78%;
}
.nb-sdb .bh-80 {
height: 80%;
}
.nb-sdb .bh-85 {
height: 85%;
}
.nb-sdb .bh-90 {
height: 90%;
}
.nb-sdb .bh-95 {
height: 95%;
}
.nb-sdb .activity-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.nb-sdb .activity-item {
display: flex;
gap: 10px;
align-items: flex-start;
}
.nb-sdb .activity-dot {
width: 8px;
height: 8px;
border-radius: 50%;
flex-shrink: 0;
margin-top: 4px;
}
.nb-sdb .dot-green {
background: var(--nb-sdb-accent-green);
}
.nb-sdb .dot-blue {
background: var(--nb-sdb-accent);
}
.nb-sdb .dot-orange {
background: var(--nb-sdb-accent-orange);
}
.nb-sdb .dot-red {
background: var(--nb-sdb-accent-red);
}
.nb-sdb .activity-text {
font-size: 0.75rem;
line-height: 1.5;
color: var(--nb-sdb-text-muted);
}
.nb-sdb .activity-text strong {
color: var(--nb-sdb-text);
}
.nb-sdb .activity-time {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.65rem;
color: var(--nb-sdb-text-dim);
margin-left: auto;
flex-shrink: 0;
}
@media (max-width: 1024px) {
.nb-sdb .stats-row {
grid-template-columns: repeat(2, 1fr);
}
.nb-sdb .chart-area {
grid-template-columns: 1fr;
}
}
@media (max-width: 640px) {
.nb-sdb .stats-row {
grid-template-columns: 1fr;
}
.nb-sdb .search-shortcut {
display: none;
}
}
@media (prefers-reduced-motion: reduce) {
.nb-sdb aside,
.nb-sdb .nav-label,
.nb-sdb .ws-info,
.nb-sdb .user-info,
.nb-sdb .collapse-btn svg {
transition: none !important;
}
}(() => {
// Scoped collapsible-sidebar wiring. State lives on the wrapper, so
// two instances of this demo on one page can each collapse
// independently.
const root = document.querySelector('.nb-sdb');
if (!root) return;
const sidebar = root.querySelector('[data-nb-sdb-sidebar]');
const toggle = root.querySelector('[data-nb-sdb-toggle]');
if (!sidebar || !toggle) return;
toggle.addEventListener('click', () => {
const collapsed = sidebar.classList.toggle('collapsed');
toggle.setAttribute('aria-expanded', !collapsed);
});
// Click to set the active nav item, scoped to this sidebar.
sidebar.querySelectorAll('.nav-item').forEach((item) => {
item.addEventListener('click', (e) => {
e.preventDefault();
sidebar.querySelectorAll('.nav-item').forEach((i) => i.classList.remove('active'));
item.classList.add('active');
});
});
})();(() => {
// Scoped collapsible-sidebar wiring. State lives on the wrapper, so
// two instances of this demo on one page can each collapse
// independently.
const root = document.querySelector('.nb-sdb');
if (!root) return;
const sidebar = root.querySelector('[data-nb-sdb-sidebar]');
const toggle = root.querySelector('[data-nb-sdb-toggle]');
if (!sidebar || !toggle) return;
toggle.addEventListener('click', () => {
const collapsed = sidebar.classList.toggle('collapsed');
toggle.setAttribute('aria-expanded', !collapsed);
});
// Click to set the active nav item, scoped to this sidebar.
sidebar.querySelectorAll('.nav-item').forEach((item) => {
item.addEventListener('click', (e) => {
e.preventDefault();
sidebar.querySelectorAll('.nav-item').forEach((i) => i.classList.remove('active'));
item.classList.add('active');
});
});
})();Here's a working CSS Navbar Design from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Vertical CSS Sidebar Navigation
Source: https://codefronts.com/navigation/css-navbars/vertical-css-sidebar-navigation/
A GitHub-dark-inspired collapsible sidebar navbar UI for a SaaS dashboard — proving that the canonical 240px ↔ 64px sidebar collapse pattern can carry a complete information density. Sidebar with gradient hex logo, a circular collapse-toggle button that rotates 180° on click, a workspace selector card (Acme Corp / Pro Plan), three nav sections (Overview / Workspace / System) with mono-uppercase labels and colour-coded badges (Live green, "12" blue, "2" orange, "3" red), and a bottom user row with gradient avatar. On collapse the entire 240px width animates to 64px — every label, badge, and the workspace info smoothly fade out — and tooltips appear on hover via a `data-label` attribute. The main pane carries a sticky topbar (breadcrumb / ⌘K search / notifications dot / command icon) and the actual dashboard content: 4-up stat cards (Revenue $84.2k +12.4%, Active Users 4,291, Deployments 138 −3.2%, Uptime 99.97%) plus a 14-bar Request Volume chart + Recent Activity feed. IBM Plex Sans + IBM Plex Mono. Best for SaaS admin panels, developer tools, internal dashboards, analytics platforms, B2B product chrome.
## HTML
```html
<section class="nb-sdb" aria-label="hexlane collapsible sidebar demo">
<aside data-nb-sdb-sidebar aria-label="Primary">
<div class="sidebar-logo">
<div class="logo-icon" aria-hidden="true">⬡</div>
<span class="logo-text">hexlane<span class="logo-dot">.</span>io</span>
</div>
<div class="workspace">
<div class="ws-avatar">A</div>
<div class="ws-info">
<div class="ws-name">Acme Corp</div>
<div class="ws-plan">Pro Plan</div>
</div>
<span class="ws-chevron" aria-hidden="true"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="6 9 12 15 18 9"/></svg></span>
</div>
<nav class="sidebar-nav" aria-label="Sections">
<div class="nav-section">
<div class="nav-section-label">Overview</div>
<a href="#" class="nav-item active" data-label="Dashboard">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg></span>
<span class="nav-label">Dashboard</span>
</a>
<a href="#" class="nav-item" data-label="Analytics">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg></span>
<span class="nav-label">Analytics</span>
<span class="nav-badge badge-green">Live</span>
</a>
<a href="#" class="nav-item" data-label="Reports">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14,2 14,8 20,8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg></span>
<span class="nav-label">Reports</span>
</a>
</div>
<div class="nav-section">
<div class="nav-section-label">Workspace</div>
<a href="#" class="nav-item" data-label="Projects">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><polygon points="12,2 2,7 12,12 22,7"/><polyline points="2,17 12,22 22,17"/><polyline points="2,12 12,17 22,12"/></svg></span>
<span class="nav-label">Projects</span>
<span class="nav-badge badge-blue">12</span>
</a>
<a href="#" class="nav-item" data-label="Team">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg></span>
<span class="nav-label">Team</span>
</a>
<a href="#" class="nav-item" data-label="Deployments">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><polyline points="22,12 18,12 15,21 9,3 6,12 2,12"/></svg></span>
<span class="nav-label">Deployments</span>
<span class="nav-badge badge-orange">2</span>
</a>
<a href="#" class="nav-item" data-label="Logs">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg></span>
<span class="nav-label">Logs</span>
</a>
</div>
<div class="nav-section">
<div class="nav-section-label">System</div>
<a href="#" class="nav-item" data-label="Alerts">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg></span>
<span class="nav-label">Alerts</span>
<span class="nav-badge badge-red">3</span>
</a>
<a href="#" class="nav-item" data-label="Settings">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg></span>
<span class="nav-label">Settings</span>
</a>
<a href="#" class="nav-item" data-label="Docs">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg></span>
<span class="nav-label">Docs</span>
</a>
</div>
</nav>
<div class="sidebar-foot">
<div class="user-row">
<div class="user-avatar">JL</div>
<div class="user-info">
<div class="user-name">Jordan Lee</div>
<div class="user-handle">admin · Acme Corp</div>
</div>
<span class="user-menu-btn" aria-hidden="true"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="5" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="12" cy="19" r="1"/></svg></span>
</div>
</div>
</aside>
<button class="collapse-btn" type="button" data-nb-sdb-toggle aria-label="Toggle sidebar" aria-expanded="true">
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="15 18 9 12 15 6"/></svg>
</button>
<div class="main">
<div class="topbar">
<div class="breadcrumb">
<span>hexlane</span>
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="9 18 15 12 9 6"/></svg>
<span>Acme Corp</span>
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="9 18 15 12 9 6"/></svg>
<strong>Dashboard</strong>
</div>
<div class="topbar-spacer"></div>
<div class="topbar-search">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
Search...
<span class="search-shortcut">⌘K</span>
</div>
<div class="topbar-actions">
<button class="topbar-icon" type="button" aria-label="Notifications">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg>
<span class="notif-dot" aria-hidden="true"></span>
</button>
<button class="topbar-icon" type="button" aria-label="Command palette">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/></svg>
</button>
</div>
</div>
<div class="content">
<h1 class="page-title">Overview</h1>
<p class="page-desc">Your workspace at a glance — updated just now</p>
<div class="stats-row">
<div class="stat-card">
<div class="stat-label">Monthly Revenue</div>
<div class="stat-value">$84.2k</div>
<div class="stat-change up"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="18 15 12 9 6 15"/></svg> +12.4%</div>
</div>
<div class="stat-card">
<div class="stat-label">Active Users</div>
<div class="stat-value">4,291</div>
<div class="stat-change up"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="18 15 12 9 6 15"/></svg> +8.1%</div>
</div>
<div class="stat-card">
<div class="stat-label">Deployments</div>
<div class="stat-value">138</div>
<div class="stat-change down"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="6 9 12 15 18 9"/></svg> −3.2%</div>
</div>
<div class="stat-card">
<div class="stat-label">Uptime SLA</div>
<div class="stat-value">99.97%</div>
<div class="stat-change up"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="18 15 12 9 6 15"/></svg> Stable</div>
</div>
</div>
<div class="chart-area">
<div class="chart-card">
<div class="chart-title">Request Volume</div>
<div class="chart-sub">Last 14 days — hover over bars</div>
<div class="chart-bars" aria-hidden="true">
<div class="bar bh-45"></div><div class="bar bh-60"></div><div class="bar bh-40"></div><div class="bar bh-70"></div><div class="bar bh-55"></div><div class="bar bh-80"></div><div class="bar active bh-90"></div><div class="bar bh-65"></div><div class="bar bh-75"></div><div class="bar bh-50"></div><div class="bar bh-85"></div><div class="bar bh-70"></div><div class="bar bh-95"></div><div class="bar bh-78"></div>
</div>
</div>
<div class="chart-card">
<div class="chart-title">Recent Activity</div>
<div class="chart-sub">Live feed</div>
<div class="activity-list">
<div class="activity-item">
<div class="activity-dot dot-green" aria-hidden="true"></div>
<div class="activity-text"><strong>Deploy succeeded</strong> — production v2.4.1</div>
<div class="activity-time">2m ago</div>
</div>
<div class="activity-item">
<div class="activity-dot dot-blue" aria-hidden="true"></div>
<div class="activity-text"><strong>Jordan Lee</strong> updated API keys</div>
<div class="activity-time">14m</div>
</div>
<div class="activity-item">
<div class="activity-dot dot-orange" aria-hidden="true"></div>
<div class="activity-text"><strong>Alert triggered</strong> — latency spike</div>
<div class="activity-time">1h</div>
</div>
<div class="activity-item">
<div class="activity-dot dot-red" aria-hidden="true"></div>
<div class="activity-text"><strong>Build failed</strong> — staging branch</div>
<div class="activity-time">2h</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
```
## CSS
```css
/* ─── 04 hexlane — collapsible sidebar dashboard navbar UI ─────── */
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap');
.nb-sdb {
--nb-sdb-sidebar-w: 240px;
--nb-sdb-sidebar-collapsed: 64px;
--nb-sdb-bg: #0d1117;
--nb-sdb-surface: #161b22;
--nb-sdb-surface-2: #21262d;
--nb-sdb-border: #30363d;
--nb-sdb-text: #e6edf3;
--nb-sdb-text-muted: #7d8590;
--nb-sdb-text-dim: #484f58;
--nb-sdb-accent: #58a6ff;
--nb-sdb-accent-green: #3fb950;
--nb-sdb-accent-orange: #d29922;
--nb-sdb-accent-red: #f85149;
--nb-sdb-accent-purple: #bc8cff;
--nb-sdb-transition: 0.22s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
width: 100%;
min-height: 720px;
background: var(--nb-sdb-bg);
color: var(--nb-sdb-text);
font-family: 'IBM Plex Sans', sans-serif;
display: flex;
overflow: hidden;
box-sizing: border-box;
}
.nb-sdb *,
.nb-sdb *::before,
.nb-sdb *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.nb-sdb aside {
width: var(--nb-sdb-sidebar-w);
background: var(--nb-sdb-surface);
border-right: 1px solid var(--nb-sdb-border);
display: flex;
flex-direction: column;
transition: width var(--nb-sdb-transition);
position: relative;
z-index: 50;
overflow: hidden;
flex-shrink: 0;
}
.nb-sdb aside.collapsed {
width: var(--nb-sdb-sidebar-collapsed);
}
.nb-sdb .sidebar-logo {
display: flex;
align-items: center;
gap: 10px;
padding: 0 16px;
height: 56px;
border-bottom: 1px solid var(--nb-sdb-border);
flex-shrink: 0;
overflow: hidden;
white-space: nowrap;
}
.nb-sdb .logo-icon {
width: 32px;
height: 32px;
border-radius: 8px;
background: linear-gradient(135deg, var(--nb-sdb-accent), var(--nb-sdb-accent-purple));
display: flex;
align-items: center;
justify-content: center;
font-size: 0.9rem;
flex-shrink: 0;
box-shadow: 0 2px 12px rgba(88,166,255,0.3);
color: #fff;
}
.nb-sdb .logo-text {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.9rem;
font-weight: 500;
letter-spacing: -0.02em;
color: var(--nb-sdb-text);
transition: opacity var(--nb-sdb-transition), width var(--nb-sdb-transition);
overflow: hidden;
}
.nb-sdb .logo-dot {
color: var(--nb-sdb-accent);
}
.nb-sdb aside.collapsed .logo-text {
opacity: 0;
width: 0;
}
/* Collapse toggle sits at the sidebar's outer edge. Lifted out of
<aside> so aside's overflow:hidden (which clips the fading labels)
doesn't also clip this button. Positioned absolute against the
wrapper; its left coord tracks the sidebar width via :has(). */
.nb-sdb .collapse-btn {
position: absolute;
top: 68px;
left: calc(var(--nb-sdb-sidebar-w) - 12px);
width: 24px;
height: 24px;
border-radius: 50%;
background: var(--nb-sdb-surface-2);
border: 1px solid var(--nb-sdb-border);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
color: var(--nb-sdb-text-muted);
transition: background 0.15s, color 0.15s, left var(--nb-sdb-transition);
z-index: 60;
}
.nb-sdb:has(aside.collapsed) .collapse-btn {
left: calc(var(--nb-sdb-sidebar-collapsed) - 12px);
}
.nb-sdb .collapse-btn:hover {
background: var(--nb-sdb-accent);
color: #fff;
border-color: var(--nb-sdb-accent);
}
.nb-sdb .collapse-btn svg {
transition: transform var(--nb-sdb-transition);
}
.nb-sdb:has(aside.collapsed) .collapse-btn svg {
transform: rotate(180deg);
}
.nb-sdb .workspace {
margin: 12px 10px;
padding: 8px 10px;
border-radius: 8px;
border: 1px solid var(--nb-sdb-border);
background: var(--nb-sdb-surface-2);
display: flex;
align-items: center;
gap: 10px;
cursor: pointer;
transition: border-color 0.15s, background 0.15s;
overflow: hidden;
white-space: nowrap;
flex-shrink: 0;
}
.nb-sdb .workspace:hover {
border-color: var(--nb-sdb-accent);
background: rgba(88,166,255,0.05);
}
.nb-sdb .ws-avatar {
width: 24px;
height: 24px;
border-radius: 6px;
background: linear-gradient(135deg, #3fb950, #1f6feb);
flex-shrink: 0;
font-size: 0.6rem;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-weight: 600;
}
.nb-sdb .ws-info {
flex: 1;
min-width: 0;
overflow: hidden;
transition: opacity var(--nb-sdb-transition), width var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .ws-info {
opacity: 0;
width: 0;
}
.nb-sdb .ws-name {
font-size: 0.75rem;
font-weight: 500;
color: var(--nb-sdb-text);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.nb-sdb .ws-plan {
font-size: 0.6rem;
color: var(--nb-sdb-text-muted);
letter-spacing: 0.05em;
text-transform: uppercase;
}
.nb-sdb .ws-chevron {
color: var(--nb-sdb-text-dim);
flex-shrink: 0;
transition: opacity var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .ws-chevron {
opacity: 0;
}
.nb-sdb .sidebar-nav {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
padding: 8px 0;
scrollbar-width: thin;
scrollbar-color: var(--nb-sdb-border) transparent;
}
.nb-sdb .sidebar-nav::-webkit-scrollbar {
width: 4px;
}
.nb-sdb .sidebar-nav::-webkit-scrollbar-thumb {
background: var(--nb-sdb-border);
border-radius: 2px;
}
.nb-sdb .nav-section {
margin-bottom: 4px;
}
.nb-sdb .nav-section-label {
font-size: 0.6rem;
font-weight: 600;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--nb-sdb-text-dim);
padding: 8px 20px 4px;
white-space: nowrap;
overflow: hidden;
transition: opacity var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .nav-section-label {
opacity: 0;
}
.nb-sdb .nav-item {
position: relative;
display: flex;
align-items: center;
gap: 10px;
padding: 7px 10px 7px 16px;
margin: 1px 8px;
border-radius: 8px;
font-size: 0.82rem;
font-weight: 400;
color: var(--nb-sdb-text-muted);
text-decoration: none;
cursor: pointer;
transition: background 0.12s, color 0.12s;
white-space: nowrap;
overflow: hidden;
user-select: none;
}
.nb-sdb .nav-item:hover {
background: var(--nb-sdb-surface-2);
color: var(--nb-sdb-text);
}
.nb-sdb .nav-item.active {
background: rgba(88,166,255,0.1);
color: var(--nb-sdb-accent);
}
.nb-sdb .nav-item.active::before {
content: '';
position: absolute;
left: 0;
top: 20%;
bottom: 20%;
width: 3px;
border-radius: 0 2px 2px 0;
background: var(--nb-sdb-accent);
}
.nb-sdb .nav-icon {
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
opacity: 0.8;
}
.nb-sdb .nav-item.active .nav-icon,
.nb-sdb .nav-item:hover .nav-icon {
opacity: 1;
}
.nb-sdb .nav-label {
transition: opacity var(--nb-sdb-transition), width var(--nb-sdb-transition);
overflow: hidden;
}
.nb-sdb aside.collapsed .nav-label {
opacity: 0;
width: 0;
}
.nb-sdb .nav-badge {
margin-left: auto;
flex-shrink: 0;
font-size: 0.6rem;
font-weight: 600;
padding: 2px 6px;
border-radius: 100px;
transition: opacity var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .nav-badge {
opacity: 0;
}
.nb-sdb .badge-blue {
background: rgba(88,166,255,0.15);
color: var(--nb-sdb-accent);
}
.nb-sdb .badge-green {
background: rgba(63,185,80,0.15);
color: var(--nb-sdb-accent-green);
}
.nb-sdb .badge-orange {
background: rgba(210,153,34,0.15);
color: var(--nb-sdb-accent-orange);
}
.nb-sdb .badge-red {
background: rgba(248,81,73,0.15);
color: var(--nb-sdb-accent-red);
}
.nb-sdb aside.collapsed .nav-item::after {
content: attr(data-label);
position: absolute;
left: calc(var(--nb-sdb-sidebar-collapsed) - 8px);
top: 50%;
transform: translateY(-50%);
background: var(--nb-sdb-surface-2);
color: var(--nb-sdb-text);
font-size: 0.75rem;
padding: 5px 10px;
border-radius: 6px;
border: 1px solid var(--nb-sdb-border);
white-space: nowrap;
pointer-events: none;
opacity: 0;
transition: opacity 0.15s;
z-index: 100;
box-shadow: 0 4px 16px rgba(0,0,0,0.4);
}
.nb-sdb aside.collapsed .nav-item:hover::after {
opacity: 1;
}
.nb-sdb .sidebar-foot {
border-top: 1px solid var(--nb-sdb-border);
padding: 10px;
flex-shrink: 0;
overflow: hidden;
}
.nb-sdb .user-row {
display: flex;
align-items: center;
gap: 10px;
padding: 6px 6px;
border-radius: 8px;
cursor: pointer;
transition: background 0.12s;
white-space: nowrap;
overflow: hidden;
}
.nb-sdb .user-row:hover {
background: var(--nb-sdb-surface-2);
}
.nb-sdb .user-avatar {
width: 32px;
height: 32px;
border-radius: 50%;
background: linear-gradient(135deg, var(--nb-sdb-accent-purple), var(--nb-sdb-accent));
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.75rem;
font-weight: 600;
color: #fff;
}
.nb-sdb .user-info {
flex: 1;
min-width: 0;
overflow: hidden;
transition: opacity var(--nb-sdb-transition), width var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .user-info {
opacity: 0;
width: 0;
}
.nb-sdb .user-name {
font-size: 0.78rem;
font-weight: 500;
color: var(--nb-sdb-text);
overflow: hidden;
text-overflow: ellipsis;
}
.nb-sdb .user-handle {
font-size: 0.65rem;
color: var(--nb-sdb-text-dim);
overflow: hidden;
text-overflow: ellipsis;
}
.nb-sdb .user-menu-btn {
color: var(--nb-sdb-text-dim);
flex-shrink: 0;
transition: opacity var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .user-menu-btn {
opacity: 0;
}
.nb-sdb .main {
flex: 1;
display: flex;
flex-direction: column;
min-height: 720px;
}
.nb-sdb .topbar {
height: 56px;
border-bottom: 1px solid var(--nb-sdb-border);
display: flex;
align-items: center;
padding: 0 24px;
gap: 16px;
background: var(--nb-sdb-surface);
flex-shrink: 0;
}
.nb-sdb .breadcrumb {
display: flex;
align-items: center;
gap: 6px;
font-family: 'IBM Plex Mono', monospace;
font-size: 0.72rem;
color: var(--nb-sdb-text-muted);
}
.nb-sdb .breadcrumb span {
color: var(--nb-sdb-text-dim);
}
.nb-sdb .breadcrumb strong {
color: var(--nb-sdb-text);
font-weight: 500;
}
.nb-sdb .topbar-spacer {
flex: 1;
}
.nb-sdb .topbar-search {
display: flex;
align-items: center;
gap: 8px;
background: var(--nb-sdb-bg);
border: 1px solid var(--nb-sdb-border);
border-radius: 8px;
padding: 6px 12px;
color: var(--nb-sdb-text-muted);
font-size: 0.75rem;
cursor: pointer;
transition: border-color 0.15s;
}
.nb-sdb .topbar-search:hover {
border-color: var(--nb-sdb-text-dim);
}
.nb-sdb .search-shortcut {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.6rem;
background: var(--nb-sdb-surface-2);
border: 1px solid var(--nb-sdb-border);
border-radius: 4px;
padding: 1px 5px;
color: var(--nb-sdb-text-dim);
margin-left: 24px;
}
.nb-sdb .topbar-actions {
display: flex;
align-items: center;
gap: 8px;
}
.nb-sdb .topbar-icon {
width: 32px;
height: 32px;
border-radius: 6px;
border: 1px solid var(--nb-sdb-border);
background: transparent;
display: flex;
align-items: center;
justify-content: center;
color: var(--nb-sdb-text-muted);
cursor: pointer;
transition: background 0.12s, color 0.12s;
position: relative;
}
.nb-sdb .topbar-icon:hover {
background: var(--nb-sdb-surface-2);
color: var(--nb-sdb-text);
}
.nb-sdb .notif-dot {
position: absolute;
top: 6px;
right: 6px;
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--nb-sdb-accent-red);
border: 1.5px solid var(--nb-sdb-surface);
}
.nb-sdb .content {
padding: 28px;
flex: 1;
}
.nb-sdb .page-title {
font-size: 1.2rem;
font-weight: 600;
color: var(--nb-sdb-text);
margin-bottom: 4px;
}
.nb-sdb .page-desc {
font-size: 0.82rem;
color: var(--nb-sdb-text-muted);
margin-bottom: 24px;
}
.nb-sdb .stats-row {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
margin-bottom: 24px;
}
.nb-sdb .stat-card {
background: var(--nb-sdb-surface);
border: 1px solid var(--nb-sdb-border);
border-radius: 12px;
padding: 18px 20px;
transition: border-color 0.15s;
}
.nb-sdb .stat-card:hover {
border-color: var(--nb-sdb-text-dim);
}
.nb-sdb .stat-label {
font-size: 0.7rem;
font-weight: 500;
letter-spacing: 0.05em;
text-transform: uppercase;
color: var(--nb-sdb-text-muted);
margin-bottom: 10px;
}
.nb-sdb .stat-value {
font-family: 'IBM Plex Mono', monospace;
font-size: 1.6rem;
font-weight: 500;
color: var(--nb-sdb-text);
line-height: 1;
margin-bottom: 8px;
}
.nb-sdb .stat-change {
font-size: 0.72rem;
display: flex;
align-items: center;
gap: 4px;
}
.nb-sdb .up {
color: var(--nb-sdb-accent-green);
}
.nb-sdb .down {
color: var(--nb-sdb-accent-red);
}
.nb-sdb .chart-area {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 16px;
}
.nb-sdb .chart-card {
background: var(--nb-sdb-surface);
border: 1px solid var(--nb-sdb-border);
border-radius: 12px;
padding: 20px;
}
.nb-sdb .chart-title {
font-size: 0.82rem;
font-weight: 500;
color: var(--nb-sdb-text);
margin-bottom: 4px;
}
.nb-sdb .chart-sub {
font-size: 0.72rem;
color: var(--nb-sdb-text-muted);
margin-bottom: 16px;
}
.nb-sdb .chart-bars {
display: flex;
align-items: flex-end;
gap: 6px;
height: 100px;
}
.nb-sdb .bar {
flex: 1;
border-radius: 4px 4px 0 0;
background: rgba(88,166,255,0.15);
border: 1px solid rgba(88,166,255,0.2);
transition: background 0.15s;
}
.nb-sdb .bar:hover {
background: rgba(88,166,255,0.35);
}
.nb-sdb .bar.active {
background: rgba(88,166,255,0.6);
border-color: var(--nb-sdb-accent);
}
.nb-sdb .bh-40 {
height: 40%;
}
.nb-sdb .bh-45 {
height: 45%;
}
.nb-sdb .bh-50 {
height: 50%;
}
.nb-sdb .bh-55 {
height: 55%;
}
.nb-sdb .bh-60 {
height: 60%;
}
.nb-sdb .bh-65 {
height: 65%;
}
.nb-sdb .bh-70 {
height: 70%;
}
.nb-sdb .bh-75 {
height: 75%;
}
.nb-sdb .bh-78 {
height: 78%;
}
.nb-sdb .bh-80 {
height: 80%;
}
.nb-sdb .bh-85 {
height: 85%;
}
.nb-sdb .bh-90 {
height: 90%;
}
.nb-sdb .bh-95 {
height: 95%;
}
.nb-sdb .activity-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.nb-sdb .activity-item {
display: flex;
gap: 10px;
align-items: flex-start;
}
.nb-sdb .activity-dot {
width: 8px;
height: 8px;
border-radius: 50%;
flex-shrink: 0;
margin-top: 4px;
}
.nb-sdb .dot-green {
background: var(--nb-sdb-accent-green);
}
.nb-sdb .dot-blue {
background: var(--nb-sdb-accent);
}
.nb-sdb .dot-orange {
background: var(--nb-sdb-accent-orange);
}
.nb-sdb .dot-red {
background: var(--nb-sdb-accent-red);
}
.nb-sdb .activity-text {
font-size: 0.75rem;
line-height: 1.5;
color: var(--nb-sdb-text-muted);
}
.nb-sdb .activity-text strong {
color: var(--nb-sdb-text);
}
.nb-sdb .activity-time {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.65rem;
color: var(--nb-sdb-text-dim);
margin-left: auto;
flex-shrink: 0;
}
@media (max-width: 1024px) {
.nb-sdb .stats-row {
grid-template-columns: repeat(2, 1fr);
}
.nb-sdb .chart-area {
grid-template-columns: 1fr;
}
}
@media (max-width: 640px) {
.nb-sdb .stats-row {
grid-template-columns: 1fr;
}
.nb-sdb .search-shortcut {
display: none;
}
}
@media (prefers-reduced-motion: reduce) {
.nb-sdb aside,
.nb-sdb .nav-label,
.nb-sdb .ws-info,
.nb-sdb .user-info,
.nb-sdb .collapse-btn svg {
transition: none !important;
}
}
```
## JavaScript
```js
(() => {
// Scoped collapsible-sidebar wiring. State lives on the wrapper, so
// two instances of this demo on one page can each collapse
// independently.
const root = document.querySelector('.nb-sdb');
if (!root) return;
const sidebar = root.querySelector('[data-nb-sdb-sidebar]');
const toggle = root.querySelector('[data-nb-sdb-toggle]');
if (!sidebar || !toggle) return;
toggle.addEventListener('click', () => {
const collapsed = sidebar.classList.toggle('collapsed');
toggle.setAttribute('aria-expanded', !collapsed);
});
// Click to set the active nav item, scoped to this sidebar.
sidebar.querySelectorAll('.nav-item').forEach((item) => {
item.addEventListener('click', (e) => {
e.preventDefault();
sidebar.querySelectorAll('.nav-item').forEach((i) => i.classList.remove('active'));
item.classList.add('active');
});
});
})();
```Here's a working CSS Navbar Design from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Vertical CSS Sidebar Navigation
Source: https://codefronts.com/navigation/css-navbars/vertical-css-sidebar-navigation/
A GitHub-dark-inspired collapsible sidebar navbar UI for a SaaS dashboard — proving that the canonical 240px ↔ 64px sidebar collapse pattern can carry a complete information density. Sidebar with gradient hex logo, a circular collapse-toggle button that rotates 180° on click, a workspace selector card (Acme Corp / Pro Plan), three nav sections (Overview / Workspace / System) with mono-uppercase labels and colour-coded badges (Live green, "12" blue, "2" orange, "3" red), and a bottom user row with gradient avatar. On collapse the entire 240px width animates to 64px — every label, badge, and the workspace info smoothly fade out — and tooltips appear on hover via a `data-label` attribute. The main pane carries a sticky topbar (breadcrumb / ⌘K search / notifications dot / command icon) and the actual dashboard content: 4-up stat cards (Revenue $84.2k +12.4%, Active Users 4,291, Deployments 138 −3.2%, Uptime 99.97%) plus a 14-bar Request Volume chart + Recent Activity feed. IBM Plex Sans + IBM Plex Mono. Best for SaaS admin panels, developer tools, internal dashboards, analytics platforms, B2B product chrome.
## HTML
```html
<section class="nb-sdb" aria-label="hexlane collapsible sidebar demo">
<aside data-nb-sdb-sidebar aria-label="Primary">
<div class="sidebar-logo">
<div class="logo-icon" aria-hidden="true">⬡</div>
<span class="logo-text">hexlane<span class="logo-dot">.</span>io</span>
</div>
<div class="workspace">
<div class="ws-avatar">A</div>
<div class="ws-info">
<div class="ws-name">Acme Corp</div>
<div class="ws-plan">Pro Plan</div>
</div>
<span class="ws-chevron" aria-hidden="true"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="6 9 12 15 18 9"/></svg></span>
</div>
<nav class="sidebar-nav" aria-label="Sections">
<div class="nav-section">
<div class="nav-section-label">Overview</div>
<a href="#" class="nav-item active" data-label="Dashboard">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg></span>
<span class="nav-label">Dashboard</span>
</a>
<a href="#" class="nav-item" data-label="Analytics">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg></span>
<span class="nav-label">Analytics</span>
<span class="nav-badge badge-green">Live</span>
</a>
<a href="#" class="nav-item" data-label="Reports">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14,2 14,8 20,8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg></span>
<span class="nav-label">Reports</span>
</a>
</div>
<div class="nav-section">
<div class="nav-section-label">Workspace</div>
<a href="#" class="nav-item" data-label="Projects">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><polygon points="12,2 2,7 12,12 22,7"/><polyline points="2,17 12,22 22,17"/><polyline points="2,12 12,17 22,12"/></svg></span>
<span class="nav-label">Projects</span>
<span class="nav-badge badge-blue">12</span>
</a>
<a href="#" class="nav-item" data-label="Team">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg></span>
<span class="nav-label">Team</span>
</a>
<a href="#" class="nav-item" data-label="Deployments">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><polyline points="22,12 18,12 15,21 9,3 6,12 2,12"/></svg></span>
<span class="nav-label">Deployments</span>
<span class="nav-badge badge-orange">2</span>
</a>
<a href="#" class="nav-item" data-label="Logs">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg></span>
<span class="nav-label">Logs</span>
</a>
</div>
<div class="nav-section">
<div class="nav-section-label">System</div>
<a href="#" class="nav-item" data-label="Alerts">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg></span>
<span class="nav-label">Alerts</span>
<span class="nav-badge badge-red">3</span>
</a>
<a href="#" class="nav-item" data-label="Settings">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg></span>
<span class="nav-label">Settings</span>
</a>
<a href="#" class="nav-item" data-label="Docs">
<span class="nav-icon" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg></span>
<span class="nav-label">Docs</span>
</a>
</div>
</nav>
<div class="sidebar-foot">
<div class="user-row">
<div class="user-avatar">JL</div>
<div class="user-info">
<div class="user-name">Jordan Lee</div>
<div class="user-handle">admin · Acme Corp</div>
</div>
<span class="user-menu-btn" aria-hidden="true"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="5" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="12" cy="19" r="1"/></svg></span>
</div>
</div>
</aside>
<button class="collapse-btn" type="button" data-nb-sdb-toggle aria-label="Toggle sidebar" aria-expanded="true">
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="15 18 9 12 15 6"/></svg>
</button>
<div class="main">
<div class="topbar">
<div class="breadcrumb">
<span>hexlane</span>
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="9 18 15 12 9 6"/></svg>
<span>Acme Corp</span>
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="9 18 15 12 9 6"/></svg>
<strong>Dashboard</strong>
</div>
<div class="topbar-spacer"></div>
<div class="topbar-search">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
Search...
<span class="search-shortcut">⌘K</span>
</div>
<div class="topbar-actions">
<button class="topbar-icon" type="button" aria-label="Notifications">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg>
<span class="notif-dot" aria-hidden="true"></span>
</button>
<button class="topbar-icon" type="button" aria-label="Command palette">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/></svg>
</button>
</div>
</div>
<div class="content">
<h1 class="page-title">Overview</h1>
<p class="page-desc">Your workspace at a glance — updated just now</p>
<div class="stats-row">
<div class="stat-card">
<div class="stat-label">Monthly Revenue</div>
<div class="stat-value">$84.2k</div>
<div class="stat-change up"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="18 15 12 9 6 15"/></svg> +12.4%</div>
</div>
<div class="stat-card">
<div class="stat-label">Active Users</div>
<div class="stat-value">4,291</div>
<div class="stat-change up"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="18 15 12 9 6 15"/></svg> +8.1%</div>
</div>
<div class="stat-card">
<div class="stat-label">Deployments</div>
<div class="stat-value">138</div>
<div class="stat-change down"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="6 9 12 15 18 9"/></svg> −3.2%</div>
</div>
<div class="stat-card">
<div class="stat-label">Uptime SLA</div>
<div class="stat-value">99.97%</div>
<div class="stat-change up"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="18 15 12 9 6 15"/></svg> Stable</div>
</div>
</div>
<div class="chart-area">
<div class="chart-card">
<div class="chart-title">Request Volume</div>
<div class="chart-sub">Last 14 days — hover over bars</div>
<div class="chart-bars" aria-hidden="true">
<div class="bar bh-45"></div><div class="bar bh-60"></div><div class="bar bh-40"></div><div class="bar bh-70"></div><div class="bar bh-55"></div><div class="bar bh-80"></div><div class="bar active bh-90"></div><div class="bar bh-65"></div><div class="bar bh-75"></div><div class="bar bh-50"></div><div class="bar bh-85"></div><div class="bar bh-70"></div><div class="bar bh-95"></div><div class="bar bh-78"></div>
</div>
</div>
<div class="chart-card">
<div class="chart-title">Recent Activity</div>
<div class="chart-sub">Live feed</div>
<div class="activity-list">
<div class="activity-item">
<div class="activity-dot dot-green" aria-hidden="true"></div>
<div class="activity-text"><strong>Deploy succeeded</strong> — production v2.4.1</div>
<div class="activity-time">2m ago</div>
</div>
<div class="activity-item">
<div class="activity-dot dot-blue" aria-hidden="true"></div>
<div class="activity-text"><strong>Jordan Lee</strong> updated API keys</div>
<div class="activity-time">14m</div>
</div>
<div class="activity-item">
<div class="activity-dot dot-orange" aria-hidden="true"></div>
<div class="activity-text"><strong>Alert triggered</strong> — latency spike</div>
<div class="activity-time">1h</div>
</div>
<div class="activity-item">
<div class="activity-dot dot-red" aria-hidden="true"></div>
<div class="activity-text"><strong>Build failed</strong> — staging branch</div>
<div class="activity-time">2h</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
```
## CSS
```css
/* ─── 04 hexlane — collapsible sidebar dashboard navbar UI ─────── */
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap');
.nb-sdb {
--nb-sdb-sidebar-w: 240px;
--nb-sdb-sidebar-collapsed: 64px;
--nb-sdb-bg: #0d1117;
--nb-sdb-surface: #161b22;
--nb-sdb-surface-2: #21262d;
--nb-sdb-border: #30363d;
--nb-sdb-text: #e6edf3;
--nb-sdb-text-muted: #7d8590;
--nb-sdb-text-dim: #484f58;
--nb-sdb-accent: #58a6ff;
--nb-sdb-accent-green: #3fb950;
--nb-sdb-accent-orange: #d29922;
--nb-sdb-accent-red: #f85149;
--nb-sdb-accent-purple: #bc8cff;
--nb-sdb-transition: 0.22s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
width: 100%;
min-height: 720px;
background: var(--nb-sdb-bg);
color: var(--nb-sdb-text);
font-family: 'IBM Plex Sans', sans-serif;
display: flex;
overflow: hidden;
box-sizing: border-box;
}
.nb-sdb *,
.nb-sdb *::before,
.nb-sdb *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.nb-sdb aside {
width: var(--nb-sdb-sidebar-w);
background: var(--nb-sdb-surface);
border-right: 1px solid var(--nb-sdb-border);
display: flex;
flex-direction: column;
transition: width var(--nb-sdb-transition);
position: relative;
z-index: 50;
overflow: hidden;
flex-shrink: 0;
}
.nb-sdb aside.collapsed {
width: var(--nb-sdb-sidebar-collapsed);
}
.nb-sdb .sidebar-logo {
display: flex;
align-items: center;
gap: 10px;
padding: 0 16px;
height: 56px;
border-bottom: 1px solid var(--nb-sdb-border);
flex-shrink: 0;
overflow: hidden;
white-space: nowrap;
}
.nb-sdb .logo-icon {
width: 32px;
height: 32px;
border-radius: 8px;
background: linear-gradient(135deg, var(--nb-sdb-accent), var(--nb-sdb-accent-purple));
display: flex;
align-items: center;
justify-content: center;
font-size: 0.9rem;
flex-shrink: 0;
box-shadow: 0 2px 12px rgba(88,166,255,0.3);
color: #fff;
}
.nb-sdb .logo-text {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.9rem;
font-weight: 500;
letter-spacing: -0.02em;
color: var(--nb-sdb-text);
transition: opacity var(--nb-sdb-transition), width var(--nb-sdb-transition);
overflow: hidden;
}
.nb-sdb .logo-dot {
color: var(--nb-sdb-accent);
}
.nb-sdb aside.collapsed .logo-text {
opacity: 0;
width: 0;
}
/* Collapse toggle sits at the sidebar's outer edge. Lifted out of
<aside> so aside's overflow:hidden (which clips the fading labels)
doesn't also clip this button. Positioned absolute against the
wrapper; its left coord tracks the sidebar width via :has(). */
.nb-sdb .collapse-btn {
position: absolute;
top: 68px;
left: calc(var(--nb-sdb-sidebar-w) - 12px);
width: 24px;
height: 24px;
border-radius: 50%;
background: var(--nb-sdb-surface-2);
border: 1px solid var(--nb-sdb-border);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
color: var(--nb-sdb-text-muted);
transition: background 0.15s, color 0.15s, left var(--nb-sdb-transition);
z-index: 60;
}
.nb-sdb:has(aside.collapsed) .collapse-btn {
left: calc(var(--nb-sdb-sidebar-collapsed) - 12px);
}
.nb-sdb .collapse-btn:hover {
background: var(--nb-sdb-accent);
color: #fff;
border-color: var(--nb-sdb-accent);
}
.nb-sdb .collapse-btn svg {
transition: transform var(--nb-sdb-transition);
}
.nb-sdb:has(aside.collapsed) .collapse-btn svg {
transform: rotate(180deg);
}
.nb-sdb .workspace {
margin: 12px 10px;
padding: 8px 10px;
border-radius: 8px;
border: 1px solid var(--nb-sdb-border);
background: var(--nb-sdb-surface-2);
display: flex;
align-items: center;
gap: 10px;
cursor: pointer;
transition: border-color 0.15s, background 0.15s;
overflow: hidden;
white-space: nowrap;
flex-shrink: 0;
}
.nb-sdb .workspace:hover {
border-color: var(--nb-sdb-accent);
background: rgba(88,166,255,0.05);
}
.nb-sdb .ws-avatar {
width: 24px;
height: 24px;
border-radius: 6px;
background: linear-gradient(135deg, #3fb950, #1f6feb);
flex-shrink: 0;
font-size: 0.6rem;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-weight: 600;
}
.nb-sdb .ws-info {
flex: 1;
min-width: 0;
overflow: hidden;
transition: opacity var(--nb-sdb-transition), width var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .ws-info {
opacity: 0;
width: 0;
}
.nb-sdb .ws-name {
font-size: 0.75rem;
font-weight: 500;
color: var(--nb-sdb-text);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.nb-sdb .ws-plan {
font-size: 0.6rem;
color: var(--nb-sdb-text-muted);
letter-spacing: 0.05em;
text-transform: uppercase;
}
.nb-sdb .ws-chevron {
color: var(--nb-sdb-text-dim);
flex-shrink: 0;
transition: opacity var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .ws-chevron {
opacity: 0;
}
.nb-sdb .sidebar-nav {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
padding: 8px 0;
scrollbar-width: thin;
scrollbar-color: var(--nb-sdb-border) transparent;
}
.nb-sdb .sidebar-nav::-webkit-scrollbar {
width: 4px;
}
.nb-sdb .sidebar-nav::-webkit-scrollbar-thumb {
background: var(--nb-sdb-border);
border-radius: 2px;
}
.nb-sdb .nav-section {
margin-bottom: 4px;
}
.nb-sdb .nav-section-label {
font-size: 0.6rem;
font-weight: 600;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--nb-sdb-text-dim);
padding: 8px 20px 4px;
white-space: nowrap;
overflow: hidden;
transition: opacity var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .nav-section-label {
opacity: 0;
}
.nb-sdb .nav-item {
position: relative;
display: flex;
align-items: center;
gap: 10px;
padding: 7px 10px 7px 16px;
margin: 1px 8px;
border-radius: 8px;
font-size: 0.82rem;
font-weight: 400;
color: var(--nb-sdb-text-muted);
text-decoration: none;
cursor: pointer;
transition: background 0.12s, color 0.12s;
white-space: nowrap;
overflow: hidden;
user-select: none;
}
.nb-sdb .nav-item:hover {
background: var(--nb-sdb-surface-2);
color: var(--nb-sdb-text);
}
.nb-sdb .nav-item.active {
background: rgba(88,166,255,0.1);
color: var(--nb-sdb-accent);
}
.nb-sdb .nav-item.active::before {
content: '';
position: absolute;
left: 0;
top: 20%;
bottom: 20%;
width: 3px;
border-radius: 0 2px 2px 0;
background: var(--nb-sdb-accent);
}
.nb-sdb .nav-icon {
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
opacity: 0.8;
}
.nb-sdb .nav-item.active .nav-icon,
.nb-sdb .nav-item:hover .nav-icon {
opacity: 1;
}
.nb-sdb .nav-label {
transition: opacity var(--nb-sdb-transition), width var(--nb-sdb-transition);
overflow: hidden;
}
.nb-sdb aside.collapsed .nav-label {
opacity: 0;
width: 0;
}
.nb-sdb .nav-badge {
margin-left: auto;
flex-shrink: 0;
font-size: 0.6rem;
font-weight: 600;
padding: 2px 6px;
border-radius: 100px;
transition: opacity var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .nav-badge {
opacity: 0;
}
.nb-sdb .badge-blue {
background: rgba(88,166,255,0.15);
color: var(--nb-sdb-accent);
}
.nb-sdb .badge-green {
background: rgba(63,185,80,0.15);
color: var(--nb-sdb-accent-green);
}
.nb-sdb .badge-orange {
background: rgba(210,153,34,0.15);
color: var(--nb-sdb-accent-orange);
}
.nb-sdb .badge-red {
background: rgba(248,81,73,0.15);
color: var(--nb-sdb-accent-red);
}
.nb-sdb aside.collapsed .nav-item::after {
content: attr(data-label);
position: absolute;
left: calc(var(--nb-sdb-sidebar-collapsed) - 8px);
top: 50%;
transform: translateY(-50%);
background: var(--nb-sdb-surface-2);
color: var(--nb-sdb-text);
font-size: 0.75rem;
padding: 5px 10px;
border-radius: 6px;
border: 1px solid var(--nb-sdb-border);
white-space: nowrap;
pointer-events: none;
opacity: 0;
transition: opacity 0.15s;
z-index: 100;
box-shadow: 0 4px 16px rgba(0,0,0,0.4);
}
.nb-sdb aside.collapsed .nav-item:hover::after {
opacity: 1;
}
.nb-sdb .sidebar-foot {
border-top: 1px solid var(--nb-sdb-border);
padding: 10px;
flex-shrink: 0;
overflow: hidden;
}
.nb-sdb .user-row {
display: flex;
align-items: center;
gap: 10px;
padding: 6px 6px;
border-radius: 8px;
cursor: pointer;
transition: background 0.12s;
white-space: nowrap;
overflow: hidden;
}
.nb-sdb .user-row:hover {
background: var(--nb-sdb-surface-2);
}
.nb-sdb .user-avatar {
width: 32px;
height: 32px;
border-radius: 50%;
background: linear-gradient(135deg, var(--nb-sdb-accent-purple), var(--nb-sdb-accent));
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.75rem;
font-weight: 600;
color: #fff;
}
.nb-sdb .user-info {
flex: 1;
min-width: 0;
overflow: hidden;
transition: opacity var(--nb-sdb-transition), width var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .user-info {
opacity: 0;
width: 0;
}
.nb-sdb .user-name {
font-size: 0.78rem;
font-weight: 500;
color: var(--nb-sdb-text);
overflow: hidden;
text-overflow: ellipsis;
}
.nb-sdb .user-handle {
font-size: 0.65rem;
color: var(--nb-sdb-text-dim);
overflow: hidden;
text-overflow: ellipsis;
}
.nb-sdb .user-menu-btn {
color: var(--nb-sdb-text-dim);
flex-shrink: 0;
transition: opacity var(--nb-sdb-transition);
}
.nb-sdb aside.collapsed .user-menu-btn {
opacity: 0;
}
.nb-sdb .main {
flex: 1;
display: flex;
flex-direction: column;
min-height: 720px;
}
.nb-sdb .topbar {
height: 56px;
border-bottom: 1px solid var(--nb-sdb-border);
display: flex;
align-items: center;
padding: 0 24px;
gap: 16px;
background: var(--nb-sdb-surface);
flex-shrink: 0;
}
.nb-sdb .breadcrumb {
display: flex;
align-items: center;
gap: 6px;
font-family: 'IBM Plex Mono', monospace;
font-size: 0.72rem;
color: var(--nb-sdb-text-muted);
}
.nb-sdb .breadcrumb span {
color: var(--nb-sdb-text-dim);
}
.nb-sdb .breadcrumb strong {
color: var(--nb-sdb-text);
font-weight: 500;
}
.nb-sdb .topbar-spacer {
flex: 1;
}
.nb-sdb .topbar-search {
display: flex;
align-items: center;
gap: 8px;
background: var(--nb-sdb-bg);
border: 1px solid var(--nb-sdb-border);
border-radius: 8px;
padding: 6px 12px;
color: var(--nb-sdb-text-muted);
font-size: 0.75rem;
cursor: pointer;
transition: border-color 0.15s;
}
.nb-sdb .topbar-search:hover {
border-color: var(--nb-sdb-text-dim);
}
.nb-sdb .search-shortcut {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.6rem;
background: var(--nb-sdb-surface-2);
border: 1px solid var(--nb-sdb-border);
border-radius: 4px;
padding: 1px 5px;
color: var(--nb-sdb-text-dim);
margin-left: 24px;
}
.nb-sdb .topbar-actions {
display: flex;
align-items: center;
gap: 8px;
}
.nb-sdb .topbar-icon {
width: 32px;
height: 32px;
border-radius: 6px;
border: 1px solid var(--nb-sdb-border);
background: transparent;
display: flex;
align-items: center;
justify-content: center;
color: var(--nb-sdb-text-muted);
cursor: pointer;
transition: background 0.12s, color 0.12s;
position: relative;
}
.nb-sdb .topbar-icon:hover {
background: var(--nb-sdb-surface-2);
color: var(--nb-sdb-text);
}
.nb-sdb .notif-dot {
position: absolute;
top: 6px;
right: 6px;
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--nb-sdb-accent-red);
border: 1.5px solid var(--nb-sdb-surface);
}
.nb-sdb .content {
padding: 28px;
flex: 1;
}
.nb-sdb .page-title {
font-size: 1.2rem;
font-weight: 600;
color: var(--nb-sdb-text);
margin-bottom: 4px;
}
.nb-sdb .page-desc {
font-size: 0.82rem;
color: var(--nb-sdb-text-muted);
margin-bottom: 24px;
}
.nb-sdb .stats-row {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
margin-bottom: 24px;
}
.nb-sdb .stat-card {
background: var(--nb-sdb-surface);
border: 1px solid var(--nb-sdb-border);
border-radius: 12px;
padding: 18px 20px;
transition: border-color 0.15s;
}
.nb-sdb .stat-card:hover {
border-color: var(--nb-sdb-text-dim);
}
.nb-sdb .stat-label {
font-size: 0.7rem;
font-weight: 500;
letter-spacing: 0.05em;
text-transform: uppercase;
color: var(--nb-sdb-text-muted);
margin-bottom: 10px;
}
.nb-sdb .stat-value {
font-family: 'IBM Plex Mono', monospace;
font-size: 1.6rem;
font-weight: 500;
color: var(--nb-sdb-text);
line-height: 1;
margin-bottom: 8px;
}
.nb-sdb .stat-change {
font-size: 0.72rem;
display: flex;
align-items: center;
gap: 4px;
}
.nb-sdb .up {
color: var(--nb-sdb-accent-green);
}
.nb-sdb .down {
color: var(--nb-sdb-accent-red);
}
.nb-sdb .chart-area {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 16px;
}
.nb-sdb .chart-card {
background: var(--nb-sdb-surface);
border: 1px solid var(--nb-sdb-border);
border-radius: 12px;
padding: 20px;
}
.nb-sdb .chart-title {
font-size: 0.82rem;
font-weight: 500;
color: var(--nb-sdb-text);
margin-bottom: 4px;
}
.nb-sdb .chart-sub {
font-size: 0.72rem;
color: var(--nb-sdb-text-muted);
margin-bottom: 16px;
}
.nb-sdb .chart-bars {
display: flex;
align-items: flex-end;
gap: 6px;
height: 100px;
}
.nb-sdb .bar {
flex: 1;
border-radius: 4px 4px 0 0;
background: rgba(88,166,255,0.15);
border: 1px solid rgba(88,166,255,0.2);
transition: background 0.15s;
}
.nb-sdb .bar:hover {
background: rgba(88,166,255,0.35);
}
.nb-sdb .bar.active {
background: rgba(88,166,255,0.6);
border-color: var(--nb-sdb-accent);
}
.nb-sdb .bh-40 {
height: 40%;
}
.nb-sdb .bh-45 {
height: 45%;
}
.nb-sdb .bh-50 {
height: 50%;
}
.nb-sdb .bh-55 {
height: 55%;
}
.nb-sdb .bh-60 {
height: 60%;
}
.nb-sdb .bh-65 {
height: 65%;
}
.nb-sdb .bh-70 {
height: 70%;
}
.nb-sdb .bh-75 {
height: 75%;
}
.nb-sdb .bh-78 {
height: 78%;
}
.nb-sdb .bh-80 {
height: 80%;
}
.nb-sdb .bh-85 {
height: 85%;
}
.nb-sdb .bh-90 {
height: 90%;
}
.nb-sdb .bh-95 {
height: 95%;
}
.nb-sdb .activity-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.nb-sdb .activity-item {
display: flex;
gap: 10px;
align-items: flex-start;
}
.nb-sdb .activity-dot {
width: 8px;
height: 8px;
border-radius: 50%;
flex-shrink: 0;
margin-top: 4px;
}
.nb-sdb .dot-green {
background: var(--nb-sdb-accent-green);
}
.nb-sdb .dot-blue {
background: var(--nb-sdb-accent);
}
.nb-sdb .dot-orange {
background: var(--nb-sdb-accent-orange);
}
.nb-sdb .dot-red {
background: var(--nb-sdb-accent-red);
}
.nb-sdb .activity-text {
font-size: 0.75rem;
line-height: 1.5;
color: var(--nb-sdb-text-muted);
}
.nb-sdb .activity-text strong {
color: var(--nb-sdb-text);
}
.nb-sdb .activity-time {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.65rem;
color: var(--nb-sdb-text-dim);
margin-left: auto;
flex-shrink: 0;
}
@media (max-width: 1024px) {
.nb-sdb .stats-row {
grid-template-columns: repeat(2, 1fr);
}
.nb-sdb .chart-area {
grid-template-columns: 1fr;
}
}
@media (max-width: 640px) {
.nb-sdb .stats-row {
grid-template-columns: 1fr;
}
.nb-sdb .search-shortcut {
display: none;
}
}
@media (prefers-reduced-motion: reduce) {
.nb-sdb aside,
.nb-sdb .nav-label,
.nb-sdb .ws-info,
.nb-sdb .user-info,
.nb-sdb .collapse-btn svg {
transition: none !important;
}
}
```
## JavaScript
```js
(() => {
// Scoped collapsible-sidebar wiring. State lives on the wrapper, so
// two instances of this demo on one page can each collapse
// independently.
const root = document.querySelector('.nb-sdb');
if (!root) return;
const sidebar = root.querySelector('[data-nb-sdb-sidebar]');
const toggle = root.querySelector('[data-nb-sdb-toggle]');
if (!sidebar || !toggle) return;
toggle.addEventListener('click', () => {
const collapsed = sidebar.classList.toggle('collapsed');
toggle.setAttribute('aria-expanded', !collapsed);
});
// Click to set the active nav item, scoped to this sidebar.
sidebar.querySelectorAll('.nav-item').forEach((item) => {
item.addEventListener('click', (e) => {
e.preventDefault();
sidebar.querySelectorAll('.nav-item').forEach((i) => i.classList.remove('active'));
item.classList.add('active');
});
});
})();
```