Chapter 07 · Wayfinding

Navigation. Finding the way.

How people move through the product and the site. Consistency here is trust.

7.1 Top nav

A pill-shaped horizontal bar with a brand dot, nav links, sign-in, and a pink CTA. Active item gets a 2px pink underline. Backdrop blurs when scrolled over content.

Marketing top nav

.tn

<nav class="tn">
  <a class="tn-brand" href="/"><span class="tn-dot"></span> MagicBlocks</a>
  <div class="tn-links">
    <a href="/product" class="is-active">Product</a>
    <a href="/solutions">Solutions</a>
    <a href="/pricing">Pricing</a>
    <a href="/docs">Docs</a>
    <a href="/blog">Blog</a>
  </div>
  <div class="tn-spacer"></div>
  <a href="/sign-in" class="tn-link">Sign in</a>
  <a href="/demo" class="tn-cta">Book a demo</a>
</nav>
.tn {
  display: flex; align-items: center; gap: var(--s-5);
  padding: var(--s-4) var(--s-6);
  background: color-mix(in oklab, var(--bg-paper) 90%, transparent);
  backdrop-filter: saturate(140%) blur(10px);
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  width: 100%; max-width: 960px;
  flex-wrap: wrap;
}
.tn-brand { display: inline-flex; align-items: center; gap: var(--s-2); font: 700 15px/1 var(--f-display); color: var(--fg); text-decoration: none; letter-spacing: -0.01em; }
.tn-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); }
.tn-links { display: inline-flex; gap: var(--s-5); }
.tn-links a {
  color: var(--fg-soft); text-decoration: none;
  font: 500 13.5px/1 var(--f-body);
  padding: 6px 0; position: relative;
  transition: color var(--dur-2) var(--ease);
}
.tn-links a:hover { color: var(--fg); }
.tn-links a.is-active { color: var(--fg); }
.tn-links a.is-active::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -4px;
  height: 2px; background: var(--accent); border-radius: 2px;
}
.tn-spacer { flex: 1; }
.tn-link { color: var(--fg-soft); text-decoration: none; font: 500 13.5px/1 var(--f-body); padding: 6px 10px; }
.tn-link:hover { color: var(--fg); }
.tn-cta {
  background: var(--accent); color: var(--paper);
  font: 600 13.5px/1 var(--f-display);
  padding: 9px var(--s-4);
  border-radius: var(--r-pill);
  text-decoration: none;
  box-shadow: var(--sh-pink);
  transition: transform var(--dur-2) var(--ease);
}
.tn-cta:hover { transform: translateY(-1px); color: var(--paper); }
import { TopNav } from "@magicblocksai/ui";

<TopNav
  brand={<a className="tn-brand" href="/"><span className="tn-dot" /> MagicBlocks</a>}
  links={[
    { href: "/product",   label: "Product", active: true },
    { href: "/solutions", label: "Solutions" },
    { href: "/pricing",   label: "Pricing" },
    { href: "/docs",      label: "Docs" },
  ]}
  actions={
    <>
      <a href="/sign-in" className="tn-link">Sign in</a>
      <a href="/demo" className="tn-cta">Book a demo</a>
    </>
  }
/>

7.2 Side nav

Compact vertical nav for in-app surfaces. Sectioned headings in mono, active item gets a pink-soft pill fill.

Side nav

.sn

<aside class="sn">
  <div class="sn-brand"><span class="sn-dot"></span> MagicBlocks</div>
  <div class="sn-section">Workspace</div>
  <a class="sn-item is-active"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="9" rx="1"/><rect x="14" y="3" width="7" height="5" rx="1"/><rect x="14" y="12" width="7" height="9" rx="1"/><rect x="3" y="16" width="7" height="5" rx="1"/></svg> <span>Overview</span></a>
  <a class="sn-item"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="9" r="3"/><path d="M12 15a5 5 0 0 0-5 5h10a5 5 0 0 0-5-5Z"/><circle cx="17" cy="7" r="2"/><path d="M21 13a3 3 0 0 0-6 0"/></svg> <span>Agents</span><span class="sn-count">6</span></a>
  <a class="sn-item"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-3.1-6.8L21 3v6h-6"/><path d="M8 10h8M8 14h5"/></svg> <span>Conversations</span><span class="sn-count">—</span></a>
  <a class="sn-item"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 10.5 12 3l9 7.5V20a2 2 0 0 1-2 2h-4v-7h-6v7H5a2 2 0 0 1-2-2z"/></svg> <span>Leads</span></a>
  <div class="sn-section">Account</div>
  <a class="sn-item"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M12 2v3M12 19v3M4.9 4.9l2.1 2.1M16.9 16.9l2.1 2.1M2 12h3M19 12h3M4.9 19.1l2.1-2.1M16.9 7.1l2.1-2.1"/></svg> <span>Settings</span></a>
</aside>
.sn {
  width: 240px;
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  padding: var(--s-5);
  display: flex; flex-direction: column; gap: 2px;
  font-family: var(--f-body);
}
.sn-brand { display: inline-flex; align-items: center; gap: var(--s-2); font: 700 14px/1 var(--f-display); padding: var(--s-2) var(--s-3) var(--s-4); }
.sn-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.sn-section { font: 500 10.5px/1 var(--f-mono); text-transform: uppercase; letter-spacing: 0.1em; color: var(--fg-faint); padding: var(--s-4) var(--s-3) var(--s-2); }
.sn-item {
  display: flex; align-items: center; gap: var(--s-3);
  padding: 8px var(--s-3);
  border-radius: var(--r-sm);
  font: 500 13.5px/1 var(--f-body);
  color: var(--fg-soft);
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur-2) var(--ease), color var(--dur-2) var(--ease);
}
.sn-item:hover { background: var(--bg-sunk); color: var(--fg); }
.sn-item.is-active {
  background: var(--accent-soft); color: var(--accent-text);
}
.sn-item.is-active svg { color: var(--accent-text); }
.sn-item > span:first-of-type { flex: 1; }
.sn-count { font-family: var(--f-mono); font-size: 11px; color: var(--fg-faint); font-weight: 500; }
.sn-item.is-active .sn-count { color: var(--accent-text); }
import { SideNav } from "@magicblocksai/ui";

<SideNav
  sections={[
    {
      heading: "Workspace",
      items: [
        { href: "/overview", label: "Overview", icon: <OverviewIcon />, active: true },
        { href: "/agents",   label: "Agents",   icon: <AgentsIcon />,   count: 6 },
        { href: "/leads",    label: "Leads",    icon: <LeadsIcon /> },
      ],
    },
    {
      heading: "Account",
      items: [
        { href: "/settings", label: "Settings", icon: <SettingsIcon /> },
      ],
    },
  ]}
/>

7.3 Tabs

Horizontal tab bar with pink underline for the active tab. Optional count chip sits right of the label. Tabs scroll horizontally on mobile.

Underline tabs

.tabs

Overview

The panel content matches the selected tab. Use Tab+arrow keys to navigate between tabs.

<div class="tabs-wrap">
  <div class="tabs" role="tablist">
    <button class="tab is-active" role="tab" type="button" id="tab-overview" aria-selected="true" aria-controls="panel-overview" tabindex="0">Overview</button>
    <button class="tab" role="tab" type="button" id="tab-conversations" aria-selected="false" aria-controls="panel-conversations" tabindex="-1">Conversations <span class="tab-count">248</span></button>
    <button class="tab" role="tab" type="button" id="tab-handoffs" aria-selected="false" aria-controls="panel-handoffs" tabindex="-1">Handoffs <span class="tab-count">14</span></button>
    <button class="tab" role="tab" type="button" id="tab-analytics" aria-selected="false" aria-controls="panel-analytics" tabindex="-1">Analytics</button>
    <button class="tab" role="tab" type="button" id="tab-settings" aria-selected="false" aria-controls="panel-settings" tabindex="-1">Settings</button>
  </div>
  <div class="tabs-body" role="tabpanel" id="panel-overview" aria-labelledby="tab-overview" tabindex="0">
    <h4 class="tabs-body-title">Overview</h4>
    <p class="tabs-body-text">The panel content matches the selected tab. Use Tab+arrow keys to navigate between tabs.</p>
  </div>
  <div class="tabs-body" role="tabpanel" id="panel-conversations" aria-labelledby="tab-conversations" tabindex="0" hidden></div>
  <div class="tabs-body" role="tabpanel" id="panel-handoffs" aria-labelledby="tab-handoffs" tabindex="0" hidden></div>
  <div class="tabs-body" role="tabpanel" id="panel-analytics" aria-labelledby="tab-analytics" tabindex="0" hidden></div>
  <div class="tabs-body" role="tabpanel" id="panel-settings" aria-labelledby="tab-settings" tabindex="0" hidden></div>
</div>
.tabs-wrap { width: 100%; } /* fluid — flows to the column width on wide layouts, internal overflow-x handles narrow */
.tabs {
  display: inline-flex; gap: 0;
  border-bottom: 1px solid var(--hair);
  width: 100%;
  overflow-x: auto;
  scrollbar-width: none;          /* Firefox: hide fat OS scrollbar */
  -ms-overflow-style: none;       /* legacy Edge / IE */
}
.tabs::-webkit-scrollbar { display: none; } /* Chrome / Safari */
.tab {
  appearance: none; background: transparent; border: 0;
  padding: 12px var(--s-4) 14px;
  font: 500 13.5px/1 var(--f-body); color: var(--fg-dim);
  cursor: pointer;
  position: relative; white-space: nowrap;
  transition: color var(--dur-2) var(--ease);
  display: inline-flex; align-items: center; gap: var(--s-2);
}
.tab:hover { color: var(--fg); }
.tab.is-active { color: var(--fg); }
.tab.is-active::after {
  content: ""; position: absolute; left: 10px; right: 10px; bottom: -1px;
  height: 2px; background: var(--accent); border-radius: 2px;
}
.tab-count {
  font-family: var(--f-mono); font-size: 11px; color: var(--fg-faint);
  padding: 2px 6px; background: var(--bg-sunk); border-radius: var(--r-xs);
}
.tab.is-active .tab-count { color: var(--accent-text); background: var(--accent-soft); }

.tabs-body { padding: var(--s-5) 0 0; }
.tabs-body-title { font: 600 15px/1.3 var(--f-display); margin: 0 0 var(--s-2); }
.tabs-body-text { font: 400 14px/1.55 var(--f-body); color: var(--fg-soft); margin: 0; }
import { Tabs } from "@magicblocksai/ui";

<Tabs
  defaultValue="overview"
  items={[
    { id: "overview",      label: "Overview",                    panel: <Overview /> },
    { id: "conversations", label: "Conversations", count: 248, panel: <Conversations /> },
    { id: "handoffs",      label: "Handoffs",      count: 14,  panel: <Handoffs /> },
    { id: "analytics",     label: "Analytics",                   panel: <Analytics /> },
    { id: "settings",      label: "Settings",                    panel: <Settings /> },
  ]}
/>

7.5 Pagination

Two patterns: numbered pagination for long lists, a compact range indicator for dense UIs. Active page fills pink.

Pagination

.pag · .pag-compact

Showing 21–40 of 248
<nav class="pag" role="navigation" aria-label="Pagination">
  <button type="button" class="pag-btn pag-arr" aria-label="Previous"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="m15 18l-6-6 6-6"/></svg></button>
  <button type="button" class="pag-btn" aria-label="Page 1">1</button>
  <button type="button" class="pag-btn is-active" aria-current="page" aria-label="Page 2">2</button>
  <button type="button" class="pag-btn" aria-label="Page 3">3</button>
  <span class="pag-ellipsis" aria-hidden="true">…</span>
  <button type="button" class="pag-btn" aria-label="Page 12">12</button>
  <button type="button" class="pag-btn pag-arr" aria-label="Next"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="m9 6 6 6-6 6"/></svg></button>
</nav>
<div class="pag-compact">
  <span class="mono small">Showing</span>
  <strong class="mono">21–40</strong>
  <span class="mono small">of</span>
  <strong class="mono">248</strong>
  <span class="pag-compact-divider"></span>
  <button class="pag-btn">Prev</button>
  <button class="pag-btn">Next <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="m9 6 6 6-6 6"/></svg></button>
</div>
.pag { display: inline-flex; gap: 4px; align-items: center; }
.pag-btn {
  min-width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; color: var(--fg-soft);
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  font: 500 13px/1 var(--f-mono);
  cursor: pointer;
  padding: 0 8px;
  gap: 4px;
  transition: background var(--dur-2) var(--ease), color var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease);
}
.pag-btn:hover { background: var(--bg-sunk); color: var(--fg); }
.pag-btn.is-active { background: var(--accent); color: var(--paper); }
.pag-arr { border-color: var(--hair); }
.pag-ellipsis { color: var(--fg-faint); padding: 0 4px; font-family: var(--f-mono); }

.pag-compact { display: inline-flex; align-items: center; gap: var(--s-2); font-size: 12.5px; color: var(--fg-soft); flex-wrap: wrap; }
.pag-compact strong { color: var(--fg); font-weight: 600; }
.pag-compact-divider { width: 1px; height: 16px; background: var(--hair); margin: 0 var(--s-2); }
import { Pagination } from "@magicblocksai/ui";
import { useState } from "react";

function Demo() {
  const [page, setPage] = useState(2);
  return (
    <>
      <Pagination total={12} page={page} onChange={setPage} />
      <Pagination total={12} page={page} onChange={setPage} compact />
    </>
  );
}

7.7 Stepper

Vertical progress indicator for flows with clear stages — onboarding, setup, wizards. Done steps fill pink; the active step pulses with a soft ring.

Vertical stepper

.stepper

  1. Connect CRM
    HubSpot · connected
  2. Build your agent
    Tone · channels · guardrails
  3. 3
    Test conversations
    Simulate 20 inbound leads
  4. 4
    Launch
    Flip the switch
<ol class="stepper">
  <li class="step is-done"><span class="step-dot">✓</span><div><div class="step-name">Connect CRM</div><div class="step-meta">HubSpot · connected</div></div></li>
  <li class="step is-done"><span class="step-dot">✓</span><div><div class="step-name">Build your agent</div><div class="step-meta">Tone · channels · guardrails</div></div></li>
  <li class="step is-active"><span class="step-dot">3</span><div><div class="step-name">Test conversations</div><div class="step-meta">Simulate 20 inbound leads</div></div></li>
  <li class="step"><span class="step-dot">4</span><div><div class="step-name">Launch</div><div class="step-meta">Flip the switch</div></div></li>
</ol>
.stepper { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0; }
.step {
  display: grid; grid-template-columns: 32px 1fr;
  gap: var(--s-4);
  padding: var(--s-3) 0;
  position: relative;
}
.step:not(:last-child)::before {
  content: ""; position: absolute;
  top: 38px; bottom: -6px; left: 15px; width: 2px;
  background: var(--hair);
}
.step.is-done::before { background: var(--accent); }
.step-dot {
  width: 32px; height: 32px; border-radius: 50%;
  background: var(--bg-paper); border: 2px solid var(--hair);
  display: inline-flex; align-items: center; justify-content: center;
  font: 600 13px/1 var(--f-mono); color: var(--fg-dim);
  position: relative; z-index: 1;
}
.step.is-done .step-dot { background: var(--accent); border-color: var(--accent); color: var(--paper); }
.step.is-active .step-dot { border-color: var(--accent); color: var(--accent-text); box-shadow: 0 0 0 4px var(--accent-soft); }
.step-name { font: 600 14.5px/1.3 var(--f-display); color: var(--fg); }
.step.is-done .step-name { color: var(--fg-soft); }
.step-meta { font: 400 12.5px/1.4 var(--f-mono); color: var(--fg-dim); }
import { Stepper } from "@magicblocksai/ui";

<Stepper
  active={2}
  steps={[
    { label: "Connect CRM",         description: "HubSpot · connected" },
    { label: "Build your agent",    description: "Tone · channels · guardrails" },
    { label: "Test conversations",  description: "Simulate 20 inbound leads" },
    { label: "Launch",              description: "Flip the switch" },
  ]}
/>

7.9 Command-K bar

A global command palette triggered by ⌘K. Centred modal with search, grouped results, and keyboard hints. The fastest path through a dense product surface.

⌘K palette

.cmdk

Live-filtered list; arrow keys move selection; Enter executes; Esc closes. Group labels use mono uppercase.

⌘K
Leads
Actions
↑↓ navigate · open · Esc close
<div class="cmdk">
  <div class="cmdk-head">
    <input class="cmdk-input" placeholder="Search…" />
    <kbd class="cmdk-kbd">⌘K</kbd>
  </div>
  <div class="cmdk-group">
    <div class="cmdk-label">Leads</div>
    <button class="cmdk-row is-active">Acme Corp</button>
  </div>
</div>
.cmdk { width: 520px; max-width: 100%; background: var(--bg-paper);
  border: 1px solid var(--hair); border-radius: var(--r-lg);
  box-shadow: var(--sh-3); overflow: hidden; }
.cmdk-head { display:flex; align-items:center; gap:var(--s-3);
  padding: var(--s-4); border-bottom: 1px solid var(--hair); }
.cmdk-input { flex:1; border:0; background:transparent; font: 400 15px/1 var(--f-body); color: var(--fg); outline:none; }
.cmdk-kbd, .cmdk-row kbd { font: 600 11px/1 var(--f-mono); padding: 3px 6px;
  background: var(--bg-sunk); border: 1px solid var(--hair);
  border-radius: var(--r-xs); color: var(--fg-soft); }
.cmdk-group { padding: var(--s-2) 0; }
.cmdk-label { font: 500 11px/1 var(--f-mono); text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--fg-dim);
  padding: var(--s-2) var(--s-4); }
.cmdk-row { display:flex; justify-content:space-between; align-items:center;
  width:100%; padding: var(--s-3) var(--s-4); border:0;
  background:transparent; font: 400 14px/1 var(--f-body); color: var(--fg);
  text-align:left; cursor:pointer; }
.cmdk-row.is-active, .cmdk-row:hover { background: var(--accent-soft); color: var(--accent-text); }
.cmdk-foot { display:flex; gap:var(--s-3); padding: var(--s-3) var(--s-4);
  border-top: 1px solid var(--hair); background: var(--bg-sunk);
  font: 400 12px/1 var(--f-body); color: var(--fg-dim); }
.skip-link-demo { position: absolute; top: -100px; left: var(--s-4);
  padding: 10px 16px; background: var(--accent); color: var(--paper);
  border-radius: var(--r-sm); font: 600 14px/1 var(--f-body);
  text-decoration: none; z-index: 10; transition: top var(--dur-2) var(--ease); }
.skip-link-demo:focus-visible { top: var(--s-4); }
import { useState } from "react";
import { CommandPalette } from "@magicblocksai/ui";

export default function Demo() {
  const [open, setOpen] = useState(true);
  return (
    <CommandPalette
      open={open}
      onOpenChange={setOpen}
      placeholder="Search leads, pages, commands…"
      groups={[
        {
          id: "leads",
          label: "Leads",
          items: [
            { id: "acme",   title: "Acme Corp — Priya Raman", shortcut: "↵", onSelect: () => {} },
            { id: "globex", title: "Globex — Tomás Ruiz",    onSelect: () => {} },
          ],
        },
        {
          id: "actions",
          label: "Actions",
          items: [
            { id: "new", title: "New conversation", shortcut: "N", onSelect: () => {} },
            { id: "dash", title: "Open dashboard",  shortcut: "D", onSelect: () => {} },
          ],
        },
      ]}
    />
  );
}

7.10 Industry bar

A slim taxonomy strip that sits directly below the top nav and above the hero on every top-level page. Answers the buyer's silent first question — is this for me? — in under half a second. Warm-neutral surface by default (with an .is-ink variant) + mono uppercase text so it reads as taxonomy, not marketing copy. Each industry links to its own page; the current industry gets an accent-dot indicator. On mobile the strip scrolls horizontally with a fade-edge hint.

Default

.industry-bar

Eyebrow FOR + 6 industries + interpunct dividers. Current industry dot-marked. Use on the homepage and every Tier 1 use-case / compare page.

<nav class="industry-bar" aria-label="Industry">
  <div class="industry-bar-track">
    <span class="industry-bar-eyebrow">For</span>
    <ul class="industry-bar-list" role="list">
      <li class="industry-bar-item">
        <a class="industry-bar-link is-current" href="/industries/mortgage" aria-current="page">
          <span class="industry-bar-dot" aria-hidden="true"></span>
          <span class="industry-bar-label">Mortgage</span>
        </a>
      </li>
      <li class="industry-bar-item">
        <span class="industry-bar-sep" aria-hidden="true">·</span>
        <a class="industry-bar-link" href="/industries/insurance"><span class="industry-bar-label">Insurance</span></a>
      </li>
      <!-- Auto · Home Services · Solar · Fintech follow the same <li> pattern -->
    </ul>
  </div>
</nav>
/* Ships in _shared.css — drop in @magicblocksai/css and use the classes. */
.industry-bar          { background: var(--bg-warm); border-bottom: 1px solid var(--hair); }
.industry-bar.is-ink   { background: var(--ink); color: var(--warm-3); }
.industry-bar-track    { display: flex; align-items: center; gap: var(--s-3);
                         height: 40px; padding: 0 var(--s-5); overflow-x: auto; }
.industry-bar.is-compact .industry-bar-track { height: 32px; }
.industry-bar-link     { font: 500 12px/1 var(--f-mono); text-transform: uppercase;
                         letter-spacing: 0.06em; color: var(--fg-soft); text-decoration: none;
                         border-bottom: 1px solid transparent; }
.industry-bar-link:hover,
.industry-bar-link:focus-visible { color: var(--accent); border-bottom-color: var(--accent); }
.industry-bar-link.is-current .industry-bar-dot {       /* accent dot before the active label */
  width: 5px; height: 5px; border-radius: 50%; background: var(--accent); }
/* + .industry-bar-eyebrow / -list / -item / -sep / -label, ink variants, mobile
   scroll-fade and focus-ring chrome — all in _shared.css */
import { IndustryBar, type IndustryBarItem } from "@magicblocksai/ui";

const INDUSTRIES: IndustryBarItem[] = [
  { slug: "mortgage",      label: "Mortgage" },
  { slug: "insurance",     label: "Insurance" },
  // …auto, home-services, solar, fintech
];

<IndustryBar industries={INDUSTRIES} currentSlug="mortgage" />

Compact

.industry-bar.is-compact

Drops the FOR eyebrow and tightens padding. Use where the strip needs to feel secondary — e.g. inside a documentation chrome or on footer secondary nav.

<!-- Compact + no eyebrow (omit the <span class="industry-bar-eyebrow">) -->
<nav class="industry-bar is-compact" aria-label="Industry">
  <div class="industry-bar-track">
    <ul class="industry-bar-list" role="list">
      <li class="industry-bar-item"><a class="industry-bar-link" href="/industries/mortgage"><span class="industry-bar-label">Mortgage</span></a></li>
      <li class="industry-bar-item"><span class="industry-bar-sep" aria-hidden="true">·</span><a class="industry-bar-link" href="/industries/insurance"><span class="industry-bar-label">Insurance</span></a></li>
      <!-- …auto, home-services, solar, fintech -->
    </ul>
  </div>
</nav>
.industry-bar {
  width: 100%;
  background: var(--bg-warm);
  border-bottom: 1px solid var(--hair);
  font-family: var(--font-mono, ui-monospace, "JetBrains Mono", "SF Mono", Menlo, Consolas, monospace);
}

.industry-bar.is-ink {
  background: var(--ink);
  color: var(--warm-3, #F4ECE4);
  border-bottom-color: rgba(244, 236, 228, 0.12);
}

.industry-bar-track {
  display: flex;
  align-items: center;
  gap: var(--s-3, 12px);
  height: 40px;
  padding: 0 var(--s-5, 24px);
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.industry-bar-track::-webkit-scrollbar { display: none; }

.industry-bar.is-compact .industry-bar-track { height: 32px; }

.industry-bar-eyebrow {
  flex: 0 0 auto;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 11px;
  font-weight: 500;
  color: var(--fg-faint);
}

.industry-bar.is-ink .industry-bar-eyebrow {
  color: rgba(244, 236, 228, 0.55);
}

.industry-bar-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: center;
  gap: var(--s-3, 12px);
  flex-wrap: nowrap;
}

.industry-bar-item {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3, 12px);
  white-space: nowrap;
}

.industry-bar-sep {
  color: var(--fg-faint);
  font-size: 12px;
  user-select: none;
}

.industry-bar.is-ink .industry-bar-sep {
  color: rgba(244, 236, 228, 0.35);
}

.industry-bar-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  text-decoration: none;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 12px;
  font-weight: 500;
  color: var(--fg-soft);
  padding: 4px 2px;
  border-bottom: 1px solid transparent;
  transition: color 120ms ease, border-color 120ms ease;
}

.industry-bar.is-ink .industry-bar-link {
  color: var(--warm-3, #F4ECE4);
}

@media (min-width: 1024px) {
  .industry-bar-link { font-size: 13px; }
}

.industry-bar-link:hover,
.industry-bar-link:focus-visible {
  color: var(--accent);
  border-bottom-color: var(--accent);
  outline: none;
}

.industry-bar-link:focus-visible {
  /* The kit's standard focus-ring chrome — rendered via box-shadow so it
     doesn't push the row taller. */
  box-shadow: 0 0 0 2px var(--bg-warm), 0 0 0 4px var(--accent);
  border-radius: 2px;
}

.industry-bar.is-ink .industry-bar-link:focus-visible {
  box-shadow: 0 0 0 2px var(--ink), 0 0 0 4px var(--accent);
}

/* …additional rules trimmed for brevity — see _shared.css */
// compact row · eyebrow hidden for secondary contexts (docs chrome, footers)
<IndustryBar
  industries={INDUSTRIES}
  compact
  eyebrow={false}
/>

7.13 Anatomy of the top nav

  1. 1
    1. Pill shape
    border-radius: var(--r-pill);
  2. 2
    2. Backdrop
    backdrop-filter: saturate(140%) blur(10px);
  3. 3
    3. Brand dot
    box-shadow: 0 0 0 4px var(--accent-soft);
  4. 4
    4. Active underline
    height: 2px; background: var(--accent);
  5. 5
    5. CTA
    background: var(--accent); box-shadow: var(--sh-pink);

7.16 Room tabs (top-of-page)

Top-of-page section tabs for “rooms across an entity surface” (the agent builder’s Overview / Persona / Knowledge / …). Same underline visual as <Tabs>; adds per-tab icon + count chip + a trailing slot for actions. Roving tabindex + arrow-key activation. Optionally sticky. v1.61.0 (app-team R2).

Room tabs

.tabs.tabs-rooms

Three rooms with one count chip. The chapter demo renders the first tab in the active state.

<nav role="navigation" aria-label="Agent builder rooms" class="tabs tabs-rooms">
  <div role="tablist" class="tabs-rooms-list">
    <button role="tab" aria-selected="true" aria-current="page" tabindex="0" class="tab is-active">
      <span class="tab-label">Overview</span>
    </button>
    <button role="tab" aria-selected="false" tabindex="-1" class="tab">
      <span class="tab-label">Journey</span><span class="tab-count">4</span>
    </button>
  </div>
</nav>
/* Reuses .tabs / .tab from chapter 6. Adds:
 *   .tabs-rooms { display: flex; align-items: center; }
 *   .tabs-rooms-list { flex: 1; }
 *   .tabs-rooms-trailing { margin-left: auto; }
 *   .tabs-rooms-sticky { position: sticky; top: 0; background: var(--bg-paper); }
 */
// Wire arrow-key activation in vanilla — or use the kit's RoomTabs which
// handles roving-tabindex and ←/→/Home/End for you.
import { RoomTabs, OverviewIcon, RouteIcon } from "@magicblocksai/ui";

export function AgentRooms() {
  const [current, setCurrent] = React.useState("overview");
  return (
    <RoomTabs
      ariaLabel="Agent builder rooms"
      rooms={[
        { id: "overview", label: "Overview", icon: <OverviewIcon /> },
        { id: "journey",  label: "Journey",  icon: <RouteIcon />, count: 4 },
      ]}
      current={current}
      onChange={setCurrent}
    />
  );
}