8 CSS Navbar Designs 04 / 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.

Best forSaaS admin panels, developer tools, internal dashboards, analytics platforms, B2B product chrome.

CSS + JS MIT licensed
Live Demo Open in tab

This is a full-page demo — interact inside the frame above, or open it in the playground for the full-screen experience.

Open in playground

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>
/* ─── 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');
    });
  });
})();

Search CodeFronts

Loading…