Menu
General
ButtonBadgePillsAvatarBrand lockupLayout
ContainerGrid & RowSurface & text utilitiesApp shellPage headerData Display
CardTableChartsCalendarStatsBulletsLeadersLogo wallCollapse & DisclosureTimelineValue chainDescriptionsFeedback
AlertProgressModalSlide-overSkeletonEmpty stateForms
Field & InputDropdownLead form & CTA rowDate pickerFilter barNavigation
NavSide navigationTop navigationApp switcherUser menuStepperTabsBreadcrumbPaginationTemplates
Sign-in pageSigned-out pageSettings layoutTheming
Browser tabProduct themesNavigation
Top navigation
The second console shell: sections in a bar under the header, menus on click, native so it works without JavaScript, with the drawer taking over on phones.
.topnav · .topnav__inner · .topnav__link · .topnav__item · .topnav__trigger · .topnav__menu
The second console shell. Sections live in a bar under the header and their menus open on click. The side navigation remains the default; this suits a console with a handful of sections rather than a deep one.
<nav class="topnav" aria-label="Sections">
<div class="topnav__inner">
<a class="topnav__link" href="#" aria-current="page">Dashboard</a>
<a class="topnav__link" href="#">Analytics</a>
<details class="topnav__item" data-dismiss>
<summary class="topnav__trigger">Operations<svg class="icon icon--sm topnav__chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg></summary>
<div class="card topnav__menu">
<a class="navlink" href="#">Transactions</a>
<a class="navlink" href="#">Data grid</a>
<a class="navlink" href="#">Terminals</a>
</div>
</details>
</div>
</nav>
How it behaves
- Click, never hover. Each section is a native disclosure element, so the menus open with JavaScript off. The shared console script closes an open menu on an outside press and on Escape, and returns focus to the section that opened it.
- One menu at a time when scripting is available. Without it, more than one can be open, and the layout tolerates that.
- The current section stays marked while its menu is shut, so an operator can always see where they are.
- Nothing is hidden. Every destination stays reachable at every width, and a release gate compares what the bar can reach against the drawer, which is rendered from the same definition.
- Phones use the drawer. Below 900px the bar steps aside and the drawer from the side-navigation shell takes over, so there is one phone navigation in the kit.
Markup
A console opts in with adminwrap--topnav, which hides the side
column at desktop width. The strip sits between the header and the console body,
and the drawer markup stays in place for phone widths. The header above the strip is the
same as in the side-navigation shell: the app switcher comes
first, then the menu toggle and the product lockup. The
top-navigation demo shows the whole
shell with it.
Which shell to choose
- Use the side navigation when a console has many top-level areas. A rail shows them all at once, and a bar would push most of them behind menus.
- Use the top navigation when a console has a handful of sections, up to about nine, each holding a short menu, and the horizontal bar reads as the product's spine.
- Both shells use the same navigation definition, the same header with the account menu last, and the same drawer on phones, so moving between them is a shell change rather than a rebuild.
CSS
These rules ship in the console pattern layer, admin-kits/shared/novus-admin.css, which this site and every Admin Kit flavor load after tokens.css. Copy the whole layer, or only the sections below; every value is a token.
/* The second console shell (feature 012): primary navigation in a bar under the
header, with menus that open on CLICK, never on hover. Built on native details
so it works when scripting does not run, like every other dismissable surface
here. Below the desktop breakpoint this bar steps aside and the drawer from the
side-navigation shell takes over, so there is one phone navigation in the kit.
The side-navigation shell remains the default; see the catalog for which to
choose. */
.topnav { position: relative; z-index: 50; background: var(--surface); border-bottom: 1px solid var(--border); }
/* No scroll container here. A menu is absolutely positioned inside this strip,
and an ancestor that scrolls clips it: overflow-x: auto forces overflow-y to
auto as well, so the dropdown would be cut off at the bar's own height. The
bar wraps instead, which keeps every section reachable AND visible. */
.topnav__inner { display: flex; flex-wrap: wrap; align-items: stretch; gap: var(--space-1); max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }
.topnav__link, .topnav__trigger { display: inline-flex; align-items: center; gap: var(--space-2); min-height: 2.75rem; padding: var(--space-2) var(--space-3); color: var(--text-secondary); font-size: var(--text-sm); font-weight: var(--weight-regular); white-space: nowrap; text-decoration: none; border-bottom: 2px solid transparent; cursor: pointer; transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease; }
.topnav__link:hover, .topnav__trigger:hover { color: var(--text); background: var(--bg-subtle); text-decoration: none; }
.topnav__link:focus-visible, .topnav__trigger:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* The current section stays marked while its menu is closed. */
.topnav__link[aria-current="page"], .topnav__item.is-current > .topnav__trigger { color: var(--accent-text); border-bottom-color: var(--accent); font-weight: var(--weight-bold); }
.topnav__item { position: relative; display: flex; }
.topnav__trigger { list-style: none; }
.topnav__trigger::-webkit-details-marker { display: none; }
.topnav__chevron { transition: transform 0.15s ease; }
.topnav__item[open] > .topnav__trigger .topnav__chevron { transform: rotate(180deg); }
.topnav__menu { position: absolute; inset-inline-start: 0; top: 100%; z-index: 60; min-width: 14rem; max-height: min(24rem, calc(100vh - 8rem)); overflow-y: auto; padding: var(--space-2); display: flex; flex-direction: column; gap: var(--space-1); font-size: var(--text-sm); line-height: var(--lh-sm); }
.topnav__menu .navlink { border-inline-start: 0; border-radius: var(--radius-md); }
/* A console opts into this shell with .adminwrap--topnav. Above the breakpoint the
strip is the navigation and the side column steps aside; below it the strip hides
and the drawer from the side-navigation shell takes over, unchanged. */
.adminwrap--topnav .adminbody { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 900px) {
.adminwrap--topnav .adminnav { display: none; }
.adminwrap--topnav .navtoggle { display: none; }
}
@media (max-width: 899.98px) { .topnav { display: none; } }