NS Design System
v3.0.0 · 257 tokens

56Nav menu

The panels that hang off a navbar link: a dropdown for a handful of destinations, a mega panel for a section of the site. Both are DISCLOSURES, not ARIA menus — the rows are links to pages, so they behave like links, and the only state is aria-expanded on the trigger, which is exactly what the CSS reads to show the panel.

Use it for

  • A link that leads to four or more related pages
  • Destinations that need a line of explanation — "Architect · patterns, scale, governance"
  • The mega panel when one section has three columns' worth of pages and a thing worth featuring

Not for

  • An actions menu (Duplicate, Delete…) — that is Menu in Overlays, with role="menu" and its own keyboard rules
  • Hover-only opening: it is unreachable by touch and fires by accident with a passing cursor
  • More than one promo per mega panel — two is an ad break, and a mega menu that is mostly marketing has stopped being navigation

Dropdown

Icon tile, title, one line of description. The description is not garnish — it is the whole reason a menu is navigable by someone who does not already know the product. Live: click Resources.

markup
<nav class="ns-topnav" aria-label="Dropdown example">
  <a class="ns-topnav__brand" href="#"><img src="../assets/logo/favicon.svg" alt=""><span class="ns-topnav__brand-name">Namaste Salesforce</span></a>
  <ul class="ns-topnav__links">
    <li><a href="#" aria-current="page">Courses</a></li>
    <li class="ns-navitem">
      <button type="button" class="ns-topnav__trigger" data-ns-menu aria-expanded="false" aria-controls="doc-resources">Resources</button>
      <div class="ns-navmenu" id="doc-resources">
        <p class="ns-navmenu__label">Read</p>
        <a class="ns-navmenu__item" href="#">
          <span class="ns-navmenu__icon"><i class="ph ph-article" aria-hidden="true"></i></span>
          <span><span class="ns-navmenu__title">Blog</span><span class="ns-navmenu__desc">Release notes, deep dives, opinions</span></span>
        </a>
        <a class="ns-navmenu__item" href="#">
          <span class="ns-navmenu__icon"><i class="ph ph-book-open-text" aria-hidden="true"></i></span>
          <span><span class="ns-navmenu__title">Docs</span><span class="ns-navmenu__desc">The theme and the design system</span></span>
        </a>
        <hr class="ns-navmenu__sep">
        <p class="ns-navmenu__label">Watch</p>
        <a class="ns-navmenu__item" href="#">
          <span class="ns-navmenu__icon"><i class="ph ph-video" aria-hidden="true"></i></span>
          <span><span class="ns-navmenu__title">YouTube</span><span class="ns-navmenu__desc">Two videos a week, Hindi and English</span></span>
        </a>
        <a class="ns-navmenu__item" href="#">
          <span class="ns-navmenu__icon"><i class="ph ph-github-logo" aria-hidden="true"></i></span>
          <span><span class="ns-navmenu__title">GitHub</span><span class="ns-navmenu__desc">The theme and this system, MIT</span></span>
        </a>
        <div class="ns-navmenu__foot">
          <span>New this week</span>
          <a href="#">Winter release →</a>
        </div>
      </div>
    </li>
    <li><a href="#">Pricing</a></li>
  </ul>
</nav>

Mega panel

.ns-navitem--mega makes the wrapper static, so the panel's containing block is the BAR and it spans the full width. Columns of the same rows, one promo, and a hairline foot bar for the odds and ends. Live: click Learn.

markup
<nav class="ns-topnav" aria-label="Mega menu example">
  <a class="ns-topnav__brand" href="#"><img src="../assets/logo/favicon.svg" alt=""><span class="ns-topnav__brand-name">Namaste Salesforce</span></a>
  <ul class="ns-topnav__links">
    <li><a href="#">Courses</a></li>
    <li class="ns-navitem ns-navitem--mega">
      <button type="button" class="ns-topnav__trigger" data-ns-menu aria-expanded="false" aria-controls="doc-learn">Learn</button>
      <div class="ns-megamenu" id="doc-learn">
        <div class="ns-megamenu__inner">
          <div class="ns-megamenu__col">
            <p class="ns-megamenu__label">By role</p>
            <a class="ns-navmenu__item" href="#"><span class="ns-navmenu__icon"><i class="ph ph-user" aria-hidden="true"></i></span><span><span class="ns-navmenu__title">Administrator</span><span class="ns-navmenu__desc">Setup, security, data model</span></span></a>
            <a class="ns-navmenu__item" href="#"><span class="ns-navmenu__icon"><i class="ph ph-code" aria-hidden="true"></i></span><span><span class="ns-navmenu__title">Developer</span><span class="ns-navmenu__desc">Apex, LWC, integrations</span></span></a>
            <a class="ns-navmenu__item" href="#"><span class="ns-navmenu__icon"><i class="ph ph-strategy" aria-hidden="true"></i></span><span><span class="ns-navmenu__title">Architect</span><span class="ns-navmenu__desc">Patterns, scale, governance</span></span></a>
          </div>
          <div class="ns-megamenu__col">
            <p class="ns-megamenu__label">By product</p>
            <a class="ns-navmenu__item" href="#"><span class="ns-navmenu__icon"><i class="ph ph-flow-arrow" aria-hidden="true"></i></span><span><span class="ns-navmenu__title">Flow</span><span class="ns-navmenu__desc">Automation without code</span></span></a>
            <a class="ns-navmenu__item" href="#"><span class="ns-navmenu__icon"><i class="ph ph-lightning" aria-hidden="true"></i></span><span><span class="ns-navmenu__title">Lightning</span><span class="ns-navmenu__desc">App Builder and components</span></span></a>
            <a class="ns-navmenu__item" href="#"><span class="ns-navmenu__icon"><i class="ph ph-database" aria-hidden="true"></i></span><span><span class="ns-navmenu__title">Data Cloud</span><span class="ns-navmenu__desc">Ingest, unify, activate</span></span></a>
          </div>
          <div class="ns-megamenu__col">
            <p class="ns-megamenu__label">Free</p>
            <a class="ns-navmenu__item" href="#"><span class="ns-navmenu__icon"><i class="ph ph-map-trifold" aria-hidden="true"></i></span><span><span class="ns-navmenu__title">Roadmaps</span><span class="ns-navmenu__desc">What to learn, in order</span></span></a>
            <a class="ns-navmenu__item" href="#"><span class="ns-navmenu__icon"><i class="ph ph-exam" aria-hidden="true"></i></span><span><span class="ns-navmenu__title">Practice exams</span><span class="ns-navmenu__desc">Timed, with explanations</span></span></a>
            <a class="ns-navmenu__item" href="#"><span class="ns-navmenu__icon"><i class="ph ph-terminal-window" aria-hidden="true"></i></span><span><span class="ns-navmenu__title">Code snippets</span><span class="ns-navmenu__desc">Copy-paste Apex and LWC</span></span></a>
          </div>
          <div class="ns-megamenu__feature">
            <span class="ns-megamenu__feature-kicker">Featured</span>
            <p class="ns-megamenu__feature-title">Admin → Developer in 12 weeks</p>
            <p class="ns-megamenu__feature-text">The full trail: Apex, testing, deployment, and the interview prep at the end.</p>
            <a class="ns-btn ns-btn--outline ns-btn--sm" href="#">See the trail</a>
          </div>
        </div>
        <div class="ns-megamenu__foot">
          <a href="#"><i class="ph ph-play-circle" aria-hidden="true"></i> Latest lesson</a>
          <a href="#"><i class="ph ph-users-three" aria-hidden="true"></i> Community</a>
          <a href="#"><i class="ph ph-question" aria-hidden="true"></i> Help centre</a>
        </div>
      </div>
    </li>
    <li><a href="#">Pricing</a></li>
  </ul>
</nav>

Panel, open

The panel on its own, held open so the parts are readable: label, rows, hairline, foot. This specimen's trigger deliberately omits data-ns-menu, which is why clicking elsewhere does not close it.

markup
<nav class="ns-topnav" aria-label="Open panel example" style="block-size:auto;padding-block-end:14rem">
  <ul class="ns-topnav__links">
    <li class="ns-navitem">
      <button type="button" class="ns-topnav__trigger" aria-expanded="true">Resources</button>
      <div class="ns-navmenu">
        <p class="ns-navmenu__label">Read</p>
        <a class="ns-navmenu__item" href="#" aria-current="page">
          <span class="ns-navmenu__icon"><i class="ph ph-article" aria-hidden="true"></i></span>
          <span><span class="ns-navmenu__title">Blog</span><span class="ns-navmenu__desc">You are here — the row shows it with the left accent</span></span>
        </a>
        <a class="ns-navmenu__item" href="#">
          <span class="ns-navmenu__icon"><i class="ph ph-book-open-text" aria-hidden="true"></i></span>
          <span><span class="ns-navmenu__title">Docs</span><span class="ns-navmenu__desc">The theme and the design system</span></span>
        </a>
      </div>
    </li>
  </ul>
</nav>

Accessibility contract

  • The trigger is a <button> with aria-expanded and aria-controls; the state attribute and the visual state are the same fact
  • Esc closes and RETURNS FOCUS to the trigger — without that, Esc silently drops a keyboard user at the top of the document
  • ArrowDown opens and moves into the panel; Tab out of the panel closes it
  • The rows are <a> elements, so they are crawlable, middle-clickable, and announced as links because that is what they are