Navigation
The primary navigation is the menu in the site header. It is driven entirely by each language’s menu.main configuration: top-level entries render as links, and an entry with children becomes a dropdown submenu on desktop. Below 48rem, a menu button keeps the header to the brand and the button; the opened panel contains the primary links, search, and language controls.
This page’s own header renders the live component — on this site the menu holds Documentation and BHDicaire.com.
Example#
Variants#
- Desktop: direct links stay in the header; an item with one level of children reveals its submenu on hover or keyboard focus
- Mobile: the brand and menu button stay in the header; the opened panel contains every primary link, the search trigger, and the language switcher
- Active state: the current section receives the accent rule; child links use their own active class
When to use#
- The header only:
layouts/partials/header.htmlrenders the strip on every page, and no other template reuses it - Links live in configuration, never in the template —
config/_default/languages.ymlfor the main site,config/brand/languages.ymlfor the brand site, one menu per language - One level of children only: an entry with children becomes a desktop dropdown and an expanded mobile group; anything deeper never renders
- The active state is computed per section, so a blog post highlights Blog without any per-page declaration
Implementation#
menu:
main:
- identifier: docs
name: Documentation
pageRef: /docs
weight: 10
- identifier: main-site
name: BHDicaire.com
url: https://bhdicaire.com/en/
weight: 20initNavDropdowns() manages desktop submenu state. initMobileNavigation() controls the header menu button and closes the panel on Escape or when the desktop breakpoint is restored.
| Context | Trigger | Result |
|---|---|---|
| Desktop submenu | Hover or keyboard focus | The child panel opens and the parent link receives aria-expanded="true" |
| Desktop submenu | Escape | The child panel closes and focus returns to the parent link |
| Mobile header | Menu button | The primary links, search, and language controls become visible; the button state and label update |
| Mobile header | Escape or viewport change | The mobile panel closes; Escape returns focus to the menu button |
The markup in layouts/partials/header.html walks .Site.Menus.main, computes active state from the current section, and wraps an item with children in .nav-menu and .nav-submenu. The same partial places the search trigger and language switcher inside the mobile panel. The manifest lists every static i18n key this component uses; labels from menu.main remain configuration data, not i18n keys in the template.
Options#
| Option | Purpose |
|---|---|
identifier | Stable key; also what the active-state rules in the template match against |
name | Visible link text, per language |
pageRef | Content path of the target page; a bad path fails the build |
url | External or literal URL, for entries that point off-site |
parent | Makes the entry a child of another; one level only |
weight | Sort order within the menu |
Interface manifest
- Kind
- Component
- Category
- Navigation
- Status
- Implemented
- Implementation
- Partial:
layouts/partials/header.htmlCSS:assets/css/site.cssJavaScript:assets/js/site.jsi18n:mainNavigationnavigationMenuOpennavigationMenuCloseConfiguration:config/_default/languages.ymlconfig/brand/languages.yml - Used by
layouts/partials/header.html- Related interfaces
- BreadcrumbsDocumentation sidebarLanguage toggle
Accessibility#
- The menu button has an accessible label from
navigationMenuOpenornavigationMenuClose, controls the primary-navigation panel, and exposes its state witharia-expanded - The strip is a single
<nav>landmark, localized through themainNavigationi18n key, which distinguishes it from the header’s language switcher and the footer’s navigation landmarks - A desktop parent entry stays a real link and carries
aria-haspopup="true", so it both signals the submenu and works as a destination in its own right;initNavDropdowns()keeps itsaria-expandedsynchronized with visible desktop submenu state - Keyboard: Tab reaches the menu button and then the opened controls; Escape closes an open mobile panel or desktop submenu and returns focus to its trigger
- Avoid nesting menu entries more than one level deep — the template renders a single pass over
.Children, so a third level would silently never appear