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