Side Menu - National Design System

A persistent sidebar for navigating sections and pages within a site, with collapsible accordion groups, responsive slide-in and top dropdown modes, and active page tracking.

Side Menu Structure

The side menu sits inside the content layout wrapper alongside the main content area. It uses the drawer component internally for scrollable, collapsible list navigation.

Component Tree
aside.nds-sidemenu ├── button.nds-sidemenu-toggle.nds-btn.nds-peek │ ├── i.hgi.hgi-stroke.hgi-menu-02.nds-icon │ └── span.nds-label.nds-truncate (toggle label, hidden on desktop) │ └── nav.nds-drawer.nds-divided.nds-full-height └── div.nds-scroll-more.nds-divided ├── ul.nds-drawer-list.nds-scroll-more-content │ ├── li (flat link) │ │ └── a.nds-btn.nds-subtle.nds-indicator │ │ └── span.nds-label │ └── li (accordion section) │ ├── button.nds-btn.nds-subtle.nds-menu-btn.nds-indicator │ │ ├── span.nds-label │ │ └── span.nds-tag (optional count) │ └── ul (submenu) │ ├── li (flat link) │ │ └── a.nds-btn.nds-subtle.nds-indicator │ │ └── span.nds-label │ └── li.nds-drawer-group (optional 3rd level) │ ├── button.nds-btn.nds-subtle.nds-indicator │ │ ├── span.nds-label │ │ └── span.nds-tag (optional count) │ └── ul (group submenu) │ └── li │ └── a.nds-btn.nds-subtle.nds-indicator │ └── span.nds-label └── button.nds-show-more.nds-btn.nds-subtle └── i.hgi.hgi-stroke.hgi-arrow-down-01

Default Side Menu

The standard sidebar layout with flat links and collapsible accordion groups. On desktop it stays fixed beside the content. On tablet and mobile it slides in from the edge with a toggle button.

Side Menu with Accordion Groups

Grouped Navigation

Add a third level by placing li.nds-drawer-group items inside a section's submenu. Each group gets its own collapsible button. Use a count tag to show the number of items at a glance.

Section → Group → Item

Responsive Modes

On screens below 960px the side menu switches from a persistent sidebar to one of two mobile-friendly patterns, controlled by the layout wrapper class.

Responsive Mode

Mode Comparison

ModeClass / Front MatterMobile BehaviorBest For
Slider (none, default) Fixed panel slides in from the edge with a floating toggle button. Body scroll is not locked. Long navigation lists where users may need to scroll the menu independently
Top Submenu nds-top Full-width bar with the active page label. Tapping it drops the drawer down from below the header. Body scroll is locked. Short navigation lists or content-heavy pages where edge slide-in would feel intrusive

Active Page Tracking

Mark the current page by adding data-state="active" to its <li> element. The JS automatically expands all parent accordion groups so the active item is visible on load.

Active Item in a Nested Group

Built-in Features

Auto-initialization

Activates when .nds-sidemenu is on the page. Toggle button, close-on-click-outside, and Escape key handling all attach automatically. Accordion behavior is provided by the Drawer component.

Active Page Tracking

Set data-state="active" on a menu item and all parent accordion groups expand on load so the current page is always visible.

Dual Responsive Modes

Choose between a slide-in sidebar panel or a top dropdown bar for mobile. Switch modes by adding nds-top to the sidemenu or setting sidemenu_mode: top in front matter.

Animated Accordion Groups

Nested groups expand and collapse with smooth height transitions. Opening one group automatically closes its siblings.

Peek Toggle Button

The floating toggle button reveals itself briefly on page load and reappears as the cursor approaches, giving users a visual hint without obstructing content.

Programmatic Control

Call NDS.Sidemenu.init() to re-initialize after dynamic content changes or SPA route transitions.

Usage Guidelines

Best Practices

  • Use the side menu for sites with hierarchical page structures where users need to jump between sections: documentation, admin consoles, multi-step workflows
  • Use the side menu alongside the Header for primary navigation. The header handles global actions and top-level links while the side menu handles section-level navigation
  • Choose top submenu mode (nds-top) when the navigation list is short (under 10 items) or the content area needs full viewport width on mobile
  • Choose slider mode (default) for longer navigation trees or when users frequently switch between pages and benefit from a persistent, independently scrollable menu
  • Do not use the side menu for simple linear flows or single-page sites. Use Stepper for sequential processes or Tabs for switching between views on the same page
  • Use two levels for most navigation trees. Use the three-level grouped pattern (with nds-drawer-group) only when the section has enough items to benefit from categorization, such as a large component library
  • Always set data-state="active" on the current page's <li> so users can orient themselves
  • Group related pages under a single accordion parent with a clear category label. Avoid mixing unrelated items in the same group
  • Add nds-cardView to the layout wrapper when the page design calls for rounded, card-like containers. This applies border-radius to the sidebar
  • Hide the side menu entirely with sidemenu_mode: false in front matter on pages that do not need section navigation (landing pages, full-width dashboards)

Modifier Classes

ClassApplied ToDescription
nds-top .nds-sidemenu Switches mobile behavior from slide-in sidebar to top dropdown bar
nds-cardView .nds-content-layout Adds border-radius to the sidebar for a card-like appearance
nds-peek .nds-sidemenu-toggle Enables the proximity-aware peek animation on the toggle button
nds-divided .nds-drawer Adds separator lines between menu items (from the drawer component)
nds-full-height .nds-drawer Stretches the drawer to fill the sidebar height

Data Attributes

AttributeDescription
data-state="active" Set on <li> to mark the current page. Parent accordion groups expand automatically on initialization.
data-state="open" Managed by JS on accordion groups and the sidebar itself. Indicates the element is expanded or visible.
aria-expanded Set on accordion group buttons. Updated automatically by JS when groups expand or collapse.

CSS Custom Properties

PropertyDefaultDescription
--nds-sidemenu-width Set in variables Width of the sidebar panel
--drawer-max-height calc(100svh - nav - spacing) Maximum height of the drawer before scroll overflow activates. Recalculated dynamically in slider mode.
--toggle-height 40px Height of the toggle button
--toggle-pos 40svh Vertical position of the floating toggle button in slider mode

JavaScript API

The NDS.Sidemenu namespace exposes a single initialization method. The component auto-initializes when .nds-sidemenu is present on the page, but you can call init() manually after dynamic content changes.

// ── Initialization ────────────────────────────────── // Auto-runs on page load via nds-loader when .nds-sidemenu exists. // Call manually after injecting a new sidemenu into the DOM: NDS.Sidemenu.init(); // ── What init() sets up ───────────────────────────── // - Toggle button: shown on tablet/mobile, opens/closes // the sidebar with backdrop overlay // - Close triggers: click outside, Escape key, or // viewport width change all close the menu // - Peek behavior: the toggle button flashes on load // and reappears when the cursor moves near it // // Accordion toggle and active state expansion are handled // by the drawer component (NDS.Drawer) automatically. // ── Backdrop integration ──────────────────────────── // Uses NDS.Backdrop.show() / .hide() for the overlay. // In slider mode, body scroll remains unlocked. // In top submenu mode, body scroll locks while open. // ── Drawer overflow ───────────────────────────────── // Handled automatically by the .nds-scroll-more wrapper // inside the drawer (shows/hides the "show more" button // and edge mask-fade via its own ResizeObserver).
Was this page useful?
60% of users said Yes from 2843 Feedbacks