Responsive State
Permanently expanded on tablet and above, collapsible with toggle arrows on mobile
Fit Mode
Stretches to fill parent height for equal-height columns in grid layouts
Latest Updates
Rich List Items
List items with icon, title, status tag, and a description on a second row. Status on the <li data-status> cascades to the featured icon and tag automatically.
- success Document Approved Your business license application has been reviewed and approved by the licensing authority.
- warning Payment Overdue Your annual business registration fee of 1,200 SAR is past due. Complete payment to avoid service suspension.
- info System Maintenance Scheduled maintenance window from 2:00 AM to 4:00 AM on Friday. Some services may be unavailable.
- error Login Attempt Blocked An unauthorized login attempt was detected from an unrecognized device. Your account has been temporarily locked.
- info New Message Received You have a new message from the Ministry of Commerce regarding your trade license renewal.
View all notifications
Built-in Features
Works on page load with just HTML markup. For dynamically added drawers, call reinit() to activate new instances.
Smooth animated expand and collapse with automatic sibling closing. Submenus nest to any depth and inherit the same animation, indicator, and state tracking at every level.
Open, closing, and active states tracked via data-state with custom events on every transition. Active nested items auto-reveal their parent menus on load.
Static expanded list on desktop that collapses into an accordion on mobile, controlled per-drawer or per-item with a single data attribute.
Height-constrained mode with gradient fade and a show-more button that auto-detects overflow and flips at scroll end.
Programmatic toggle, overflow check, init, destroy, and custom events fired on every submenu open and close.
Usage Guidelines
Best Practices
- Use drawers for sidebar navigation with nested menu structures. The accordion behavior keeps the interface tidy by closing siblings automatically when a new submenu opens.
- Works equally well for flat link lists like quick links, latest updates, promotional items, or related resources where no nesting is needed.
- Use the Rich List Items layout for inline notification feeds, activity lists, or any list where each row needs an icon, title, status tag, and a supporting description line.
- Do not use a drawer for top-level page navigation. Use the Header instead, which is built to host primary nav, search, and user controls.
- Do not use a drawer for compact action menus attached to a single trigger. Use the Dropmenu, which handles positioning and dismissal for overlay menus.
- Reach for
nds-fitwhen the drawer sits in a grid column that should match the height of sibling cards. Combine withnds-cardandnds-strokefor a framed block. - Add
nds-dividedwhen rows carry multi-line content (descriptions, timestamps, tags). Leave it off for dense flat link lists where the indicator alone is enough visual separation. - Submenus nest to any depth, but keep trees shallow (two or three levels) for readability. Deeper structures read like a tangled outline and often hint at a page that should be split up.
- Mark the current page with
data-state="active"on the deepest<li>. The drawer automatically opens all ancestor submenus on load so users land with the active path revealed. - Constrain long lists by setting
--drawer-max-heighton the<nav>and wrapping the list in.nds-scroll-more. The fade mask and show-more button appear only when content actually overflows. - Apply
nds-oncolorwhen the drawer sits on a dark or tinted surface. It rebalances dividers and indicators so rows remain legible without touching text colors.
Modifier Classes
| Class | Description |
|---|---|
nds-sm |
Compact size with tighter indentation (--spacing-lg) and a 2px active indicator. |
nds-lg |
Roomier size with wider indentation (--spacing-2xl) and a 4px active indicator. |
nds-divided |
Adds horizontal divider lines between list items. Useful for rows with multi-line content. |
nds-fit |
Stretches the drawer to fill its parent height for equal-height columns in grid layouts. |
nds-oncolor |
Rebalances dividers and indicators for use on dark or colored backgrounds. |
nds-card |
Displays the drawer as a card-width block, letting it sit alongside other cards in a grid. |
nds-lined |
Adds a vertical side rail (::before pseudo-element) alongside every sub-list. Opt-in — add to .nds-drawer. Used by the site sidemenu and TOC. Rail width and block-axis inset are controlled by --drawer-lined-width and --drawer-lined-block. |
nds-drawer-group |
Applied to a li inside a sub-ul to create a 3-level collapsible group. The group renders as a bold header button that expands a nested sub-list. Restores display: flex and full text color that the muted sub-list styles normally suppress. |
nds-divided on ul |
Applied to an inner sub-ul (not the drawer root) to add border-block-end dividers between its immediate children. The last child never gets a divider. Useful for separating group items within a 3-level drawer. |
Data Attributes
| Attribute | Description |
|---|---|
data-state="active" |
Set on <li> to mark the current page. The button indicator activates and parent menus expand automatically. |
data-open-on |
Set on drawer or individual <li>. Submenus start expanded at the matching breakpoint but remain toggleable. tablet opens on tablet and everything larger. tablet-max opens on tablet and everything smaller, closed on desktop. Values: mobile, tablet, tablet-max, desktop, desktop-max, large-desktop, always, never. |
data-always-open-on |
Set on drawer only. Locks all submenus open and disables interaction at the matching breakpoint. Arrows hidden, buttons non-clickable. Below that breakpoint, reverts to normal accordion. Same values as data-open-on. |
CSS Custom Properties
| Property | Default | Description |
|---|---|---|
--drawer-gap |
0px |
Vertical spacing between list items. |
--drawer-indent |
var(--spacing-md) |
Submenu indentation. Increases with nds-sm and nds-lg. |
--drawer-divider |
var(--divider-color) |
Color of the divider lines when nds-divided is applied. |
--drawer-indicator-width |
5px |
Thickness of the active/hover indicator bar. Overridden by nds-sm (2px) and nds-lg (4px). |
--drawer-indicator |
transparent |
Default indicator color for inactive items. |
--drawer-indicator-active |
var(--background-primary) |
Indicator color for the active item (data-state="active"). |
--drawer-indicator-hover |
var(--colors-neutral-400) |
Indicator color on hover. |
--drawer-truncate |
1 |
Maximum number of visible lines per label before truncation. |
--drawer-transition |
var(--nds-transition) |
Animation timing for submenu expand and collapse. |
--drawer-max-height |
400px |
Maximum height before scroll overflow activates (requires .nds-scroll-more wrapper). |
--drawer-btn-height |
fit-content |
Height applied to each row button. Set to 100% when nds-fit is used. |
--drawer-btn-gap |
var(--spacing-md) |
Gap between the icon, label, and trailing content inside a row. |
--drawer-lined-width |
2px |
Width of the vertical side rail rendered by nds-lined. |
--drawer-lined-block |
0px |
Block-axis inset (top and bottom trim) of the side rail. Increase to shorten the rail so it does not reach the very top or bottom edge of its sub-list. |
JavaScript API
NDS.Drawer initializes automatically on page load for all .nds-drawer elements. For dynamically added drawers, call NDS.Drawer.create(element) (legacy alias: NDS.Drawer.initDrawer).