Usage
Aside is the container for the app shell's right-side rail + drawer pattern. A persistent rail of Aside Trigger buttons sits against the edge of the screen, and each one opens an Aside Drawer panel of secondary content next to the main view.
Import the parts you need — each import registers its custom element:
import "@nordhealth/components/lib/Aside"
import "@nordhealth/components/lib/AsideDrawer"
import "@nordhealth/components/lib/AsideTrigger"
Then compose the triggers in the rail slot and the drawers in the default slot:
Composition
Aside lays out a fixed-width rail and, when a drawer is active, a resizable drawer panel beside it. The active-drawer attribute holds the id of the open drawer (empty closes them all), so a trigger, its drawer and the container stay in sync.
Aside
├── rail (slot)
│ └── AsideTrigger (one per drawer, toggles it)
└── AsideDrawer (one or more panels, default slot)
└── Drawer content
<nord-aside active-drawer="details">
<nord-aside-trigger slot="rail" drawer="details" icon="interface-info" label="Details"></nord-aside-trigger>
<nord-aside-trigger slot="rail" drawer="activity" icon="interface-time" label="Activity"></nord-aside-trigger>
<nord-aside-drawer id="details">
<!-- drawer content -->
</nord-aside-drawer>
<nord-aside-drawer id="activity">
<!-- drawer content -->
</nord-aside-drawer>
</nord-aside>
Aside
Aside owns the layout and the open state. Set active-drawer to the id of the drawer to show (or "" to close), tune the rail with rail-width and rail-gap, and choose what the resize handle does with handle-click (toggle, close or none). It emits active-drawer-change, drawer-open, drawer-close, drawer-resize and handle-mode-change so your app can react to or persist the state.
Aside Drawer
Aside Drawer is a panel of content shown beside the rail. Give each one a unique id that its trigger and the container's active-drawer reference. It is resizable between min-width and max-width (starting at default-width), can expand to fullscreen, and emits width-change as it resizes.
Aside Trigger
Aside Trigger is a rail button that toggles a drawer. Point drawer at the target drawer's id, give it an icon and a label (used as the accessible name and the hover tooltip), and optionally a badge. Place it in the container's rail slot.
A trigger can also act as a navigation link: set href (with optional target and rel) instead of drawer, and it renders a real anchor — so a rail can mix drawer toggles and page links with the same look. drawer and href are mutually exclusive; when both are set, href wins.
<nord-aside>
<!-- opens a drawer -->
<nord-aside-trigger slot="rail" drawer="chat" icon="interface-chat" label="Chat"></nord-aside-trigger>
<!-- navigates like a link -->
<nord-aside-trigger slot="rail" href="/notifications" icon="navigation-notifications" label="Notifications"></nord-aside-trigger>
<nord-aside-drawer id="chat">
<!-- drawer content -->
</nord-aside-drawer>
</nord-aside>
Examples
Rail collapse layout
Embedded in an app shell, the rail tucks against the edge of the layout and the active drawer opens beside the main content.
Multiple drawers
Add a trigger and a drawer per panel. Opening one drawer closes the others, since only one active-drawer is open at a time.
Badges and disabled triggers
A trigger can carry a badge to flag new or pending content, and be disabled when its drawer isn't available.
Resizable drawers
Drag the handle between the drawer and the main view to resize it between its min-width and max-width; arrow keys nudge it while the handle is focused.
Fullscreen
A drawer can expand to fill the available space for focused, content-heavy tasks.
Accessibility
- Give every Aside Trigger a
label. It becomes the button's accessible name and its hover tooltip, so the icon-only rail is understandable to assistive technology. - The container reflects each drawer's open state with
aria-expandedon its trigger, so screen reader users hear whether a panel is open or closed. - A trigger's
badgeis decorative; convey the same information in the drawer's content or the trigger'slabelso it isn't lost to assistive technology. - The resize handle is keyboard operable — it is focusable and responds to the arrow keys — so a drawer can be resized without a pointer.
Templates
See this component composed into complete application views:
API reference
Aside
Container for the right-side rail + drawer pattern in the app shell.
<nord-accordion></nord-accordion>Props
| Property | Attribute | Description | Type | Default |
|---|---|---|---|---|
activeDrawer | active-drawer | The id of the currently-active <nord-aside-drawer>. Empty string
means no drawer is open. Setting to an unknown / disabled id is a
silent no-op. | string | '' |
railWidth | rail-width | Width of the rail column in px. | number | 48 |
railGap | rail-gap | Gap between rail and the active drawer panel in px. | number | 0 |
handleClick | handle-click | Controls what clicking (no-drag) the resize handle does. Drag-for-resize is independent of this attribute. | AsideHandleClick | 'toggle' |
Slots
| Slot name | Description |
|---|---|
rail | Free-form content placed in the rail column. |
tooltip-divider | Tooltip anchored to the resize handle on hover. |
Default slot | Default slot for <nord-aside-drawer> panels. |
| Event | Detail Type | Description |
|---|---|---|
active-drawer-change | AsideActiveDrawerChangeEvent | Dispatched when active-drawer changes, with activeDrawer / previousDrawer properties. Fires on every transition including open, switch, and close. |
drawer-open | AsideDrawerOpenEvent | Dispatched when transitioning from no active drawer to an active one (i.e. a drawer opened from the closed state). Has an activeDrawer property. |
drawer-close | AsideDrawerCloseEvent | Dispatched when all drawers close (active-drawer went from a non-empty value to empty). Has a previousDrawer property. |
drawer-resize | AsideDrawerResizeEvent | Dispatched when the active drawer's width changes, with drawerId (the specific drawer that changed) and width properties. Unlike active-drawer-change, this names a single drawer by id rather than describing a transition between drawers. |
handle-mode-change | AsideHandleModeChangeEvent | Dispatched when the resize handle's mode changes (col-resize / pointer / default). Mirrors the current value to the host's data-handle-mode attribute so consumers can also read it synchronously. Has mode / previous properties. |
CSS Properties
CSS Custom Properties provide more fine grain control over component presentation. We advise utilizing existing properties on the component before using these.
| Property | Description | Default |
|---|---|---|
--n-aside-rail-width | Controls the inline-size of the rail column. | 48px |
--n-aside-rail-gap | Controls the gap between the rail and the active drawer. | var(--n-space-s) |
--n-aside-rail-background-color | Controls the background color of the rail column. | var(--n-color-surface) |
--n-aside-background-color | Controls the background color of the aside container (matches the layout's main area by default). | var(--n-color-background) |
--n-aside-drawers-margin-inline-start | Inline-start margin of the drawers wrapper — creates a gap between the layout's main area and the active drawer card. The resize handle follows this margin so it stays at the drawer's edge. | 0 |
--n-aside-rail-narrow-block-size | Block-size of the rail when it renders as a bottom bar at <768px. | 56px |
--n-aside-rail-narrow-padding-inline | Inline padding inside the bottom rail at <768px. | var(--n-space-m) |
--n-aside-rail-narrow-padding-block | Block padding inside the bottom rail at <768px. | var(--n-space-s) |
--n-aside-rail-narrow-border-block-start-width | Top border width of the bottom rail at <768px. Set to 0 to remove. | 1px |
--n-aside-rail-narrow-border-color | Top border color of the bottom rail at <768px. | var(--n-aside-rail-border-color) |
--n-aside-drawer-floating-inset-block-start | Distance from the viewport top to the floating drawer at <768px (clears the layout header). | var(--n-layout-header-size, 60px) |
--n-aside-drawer-floating-inset-inline | Inline gap between the floating drawer and each viewport edge at <768px. Default 0 = full viewport width. | 0px |
--n-aside-drawer-slide-duration | Duration of the slide-up animation when a drawer opens at <768px. | 300ms |
--n-aside-drawer-slide-easing | Easing of the slide-up animation when a drawer opens at <768px. | cubic-bezier(0.4, 0, 0.2, 1) |
--n-aside-drawer-floating-inset-block-end | Distance from the viewport bottom to the floating drawer at <768px. By default the drawer's bottom edge meets the rail's top edge. | calc(rail-size - bottom-offset) |
--n-aside-drawer-floating-bottom-offset | Subtracts from the floating drawer's inset-block-end to let the drawer extend past the rail's top edge (visual overlap). Default 0. | 0 |
--n-aside-backdrop-background | Background color of the backdrop behind the floating drawer at <768px. | rgb(0 0 0 / 0.4) |
--n-aside-z-backdrop | z-index of the backdrop at <768px (above the sticky footer so it dims the footer too). | calc(var(--n-index-top-bar) + 2) |
--n-aside-z-drawer-floating | z-index of the floating drawer overlay at <768px (above the backdrop). | calc(var(--n-index-top-bar) + 3) |
--n-aside-z-rail-narrow | z-index of the bottom rail at <768px (above the drawer so it remains tappable). | calc(var(--n-index-top-bar) + 4) |
Parts
This component is made up of the following parts.
Aside Drawer
A drawer panel inside <nord-aside>.
<nord-accordion-header></nord-accordion-header>Props
| Property | Attribute | Description | Type | Default |
|---|---|---|---|---|
defaultWidth | default-width | Initial width in px. The persisted value overrides this on load; if
default-width changes between sessions, the persisted value is
re-seeded to the new default. | number | 420 |
minWidth | min-width | Resize clamp lower bound in px. | number | 280 |
maxWidth | max-width | Resize clamp upper bound in px. Defaults to Number.MAX_SAFE_INTEGER
so an unset max-width doesn't constrain the drawer — the consumer's
layout (or the rail / nav anchoring) determines the practical ceiling.
Set an explicit value to clamp.
Not reflected: an unset cap is the Number.MAX_SAFE_INTEGER sentinel,
which must never render into the DOM as max-width="9007199254740991". | number | — |
maxFullscreenWidth | max-fullscreen-width | Maximum inline-size in px the drawer can reach when [fullscreen]
is active. Independent of max-width (which only caps the docked
drag / keyboard resize) — fullscreen typically wants to grow
larger than the docked maximum. Defaults to Number.MAX_SAFE_INTEGER
so an unset value lets fullscreen fill all available room (bounded
by the layout's left-cap rule in <nord-aside>).
Not reflected: an unset cap is the Number.MAX_SAFE_INTEGER sentinel,
which must never render into the DOM. | number | — |
disabled | disabled | When set, the drawer cannot be opened. Programmatic opens are silently ignored; if the drawer is already open and this flips on, the drawer stays open until closed normally. | boolean | false |
fullscreen | fullscreen | Reflected. Phase 3 wires the overlay sizing internally. | boolean | false |
floating | floating | Set by the parent <nord-aside> when the drawer renders as a narrow
floating overlay (rather than a docked region). When true the host
becomes an accessible modal dialog (role="dialog" + aria-modal);
when false the host is a role="region" landmark. Drive this only
through the parent — it owns the floating-vs-docked decision. | boolean | false |
Slots
| Slot name | Description |
|---|---|
Default slot | Default slot. Place arbitrary drawer content here. |
| Event | Detail Type | Description |
|---|---|---|
width-change | AsideDrawerWidthChangeEvent | Dispatched when the drawer's width changes. The event exposes width (the new applied inline-size in px) and source ('drag' | 'keyboard' | 'attribute' | 'storage'). |
Aside Trigger
Rail button that toggles a <nord-aside-drawer> inside <nord-aside>,
or navigates like a link when href is set.
<nord-accordion-item></nord-accordion-item>Props
| Property | Attribute | Description | Type | Default |
|---|---|---|---|---|
drawer | drawer | The id of the <nord-aside-drawer> this trigger toggles.
Mutually exclusive with href — when both are set, href wins and
the trigger acts as a link instead of a drawer toggle. | string | '' |
href | href | When provided, renders the trigger as a link that navigates to the
given URL instead of toggling a drawer. Mutually exclusive with
drawer. Mirrors nord-button's link mode, so middle-click,
cmd/ctrl-click and right-click behave like a real anchor. | string | undefined | — |
target | target | When provided together with a href property, determines where to open the linked URL. Forwarded to the underlying anchor. | '_self' | '_blank' | '_parent' | '_top' | undefined | — |
rel | rel | When provided together with a href property, sets the relationship between the linked URL and the current document, e.g. “noopener noreferrer” when linking to untrusted content in a new tab. | string | undefined | — |
icon | icon | Nord icon name. Shortcut for the common case; equivalent to placing
<nord-icon name="…"> in the default slot. | string | undefined | — |
label | label | Accessible label (used for aria-label on the host). | string | '' |
badge | badge | Optional badge content (forwarded to inner <nord-badge>). | string | number | undefined | — |
disabled | disabled | Makes the trigger disabled. Takes precedence over the target
drawer's disabled state. | boolean | false |
tooltip | tooltip | Whether to render a <nord-tooltip> showing label on hover/focus.
Defaults to true — set tooltip="false" (or omit label) to opt out. | boolean | true |
Slots
| Slot name | Description |
|---|---|
Default slot | Overrides the icon attribute for custom leading content. |
tooltip | Overrides the tooltip body (falls back to label). Lets consumers add icons, shortcut hints, etc. — anything beyond the plain string label. |
Dependencies
This component is internally dependent on the following components:
Design guidelinesFor designers
Usage
This section includes guidelines for designers and developers about the usage of this component in different contexts.
Do
- Use as the right-side rail + drawer container in the app shell.
- Mix
<nord-aside-trigger>s with plain<nord-button>s or<a>s in therailslot — triggers toggle drawers, plain buttons/links are for navigation-only items. - Place one or more
<nord-aside-drawer>panels in the default slot; the aside shows the one whoseidmatchesactive-drawer. - Let consumers drive the open state via the
active-drawerattribute and theactive-drawer-changeevent.
Don’t
- Don’t put more than one
<nord-aside>on the page — it owns app-shell-level state. - Don’t open multiple drawers at once. The aside is single-active by design.
- Don’t wrap navigation-only rail items in
<nord-aside-trigger>— use a plain<nord-button>or<a>instead.
Additional considerations
- Owns the single-active drawer state and the inline-start resize handle. Drag-for-resize is independent of
handle-click, which only controls the click (no-drag) behaviour:toggle,close, ornone. - Width and gap of the rail column are configurable via
--n-aside-rail-widthand--n-aside-rail-gap. - Emits
active-drawer-changewith{ activeDrawer, previousDrawer }anddrawer-resizewith{ drawerId, width }.