Menu

import "@taprootio/espalier/menu";

<esp-menu>

Shared navigation primitive for top navigation, sidebar navigation, and drawer navigation.

Use mode="horizontal" for top navigation, mode="vertical" for sidebar navigation, and mode="drawer" for drawer-only navigation. The same tree of esp-menu-item and esp-menu-group children can render inline and as a drawer so consumers do not need duplicate navigation markup for desktop and mobile. An inline vertical rail keeps its intrinsic height so a page-level layout can move a tall sidebar with document scroll; the fixed drawer presentation supplies its own vertical scrolling instead.

2.4 migration: inline vertical rails no longer create their own bounded scroller. A standalone menu inside a fixed-height or overflow-hidden shell can restore that presentation by bounding and scrolling the host:

A published site usually wants the other common mobile pattern: a panel that covers the whole viewport with the site's brand centered above large, centered items. Set drawer-presentation="full-screen" for that; the side panel stays the default for application menus. The panel is modal: the content beside it goes inert, scrolling locks, focus moves in, Tab cycles its controls, and Escape closes it. Any drawer sits on the top layer, so a dialog or lightbox opened from one of its items cannot stack above it: an open drawer closes when another overlay opens, and that overlay returns focus to the drawer's trigger when it closes. An owning esp-header mirrors its configured brand into the panel and keeps its own menu toggle on the top layer so the burger closes the panel it opened:

Slots

<esp-menu> has the following slots:

Default

esp-menu-item and esp-menu-group children.

drawer-brand

Custom brand markup for the full-screen drawer. When empty, the brand an owning esp-header mirrors in renders instead.

Attributes

<esp-menu> has the following attributes:

mode

mode has a default value of "horizontal".

Rendering mode: horizontal top navigation, vertical sidebar navigation, or drawer-only navigation.

overflow

overflow has a default value of "auto".

Overflow behavior for horizontal navigation.

left-drawer and right-drawer force drawer access from the chosen side. wrap and scroll keep navigation inline. auto lets an owning component such as esp-header opt into drawer fallback when inline content does not fit.

side

side has a default value of "left".

Which side the drawer is attached to.

drawer-presentation

drawer-presentation has a default value of "panel".

How the drawer presents: panel slides a side panel in beside a scrim (the default, suited to application menus); full-screen covers the viewport from its top edge with the brand centered above large, centered items and no scrim. Unsupported values read as panel.

full-screen-transition

full-screen-transition has a default value of "fade".

Motion the full-screen drawer enters and leaves with: fade (default), slide-down from above, slide-up from below, slide-left from the right edge, or slide-right from the left edge. Timed by --esp-menu-drawer-transition-duration and disabled under reduced motion. The side panel keeps its own slide.

aria-label

aria-label has a default value of null.

Accessible label for the navigation landmark.

auto-expand

auto-expand has a default value of false.

Automatically expand groups to reveal the current page.

sliding

sliding has a default value of undefined.

Compatibility hook used by esp-header when inline navigation becomes too wide. Prefer mode/overflow in application code.

collapsed

collapsed has a default value of undefined.

Compatibility alias for the old vertical menu drawer state.

intent

intent has a default value of undefined.

The element's intent — its meaning: neutral (no pin), or success, warning, danger, info — each pinned to its fixed status family (blue for info), retunable per theme via intents. On token-emitting controls a non-neutral intent pins the filled-action pair to that family, derived over the governing zone's theme; class-styled chrome (badges, callouts, status pills) opts out of inline emission and renders its treatment from CSS classes instead. An intent never repaints the surrounding zone, which is what contexts are for. Removing the attribute restores the element's own default intent.

context

context has a default value of undefined.

A theme-defined color zone. The selected context rebinds designer-facing roles and emits a complete, contrast-enforced semantic token table on this host for descendants to inherit.

Methods

<esp-menu> has the following methods:

ownsDrawerLock

Host hook for the swipe controller: a full-screen open is modal-managed here.

openDrawer

Open the drawer overlay when this menu is drawer-capable.

Pass the control that opened the drawer so focus can return to it when the drawer closes.

closeDrawer

Close the drawer overlay.

toggleDrawer

Toggle the drawer overlay open or closed.

toggleOpened

Compatibility alias used by the old header menu integration.

traverseToClosest

Traverse up the DOM tree to find the closest element that matches the selector. This method is aware of shadow DOM boundaries and will traverse through them to find the element.

Events

<esp-menu> emits the following events:

esp-menu-drawer-opened

esp-menu-drawer-opened is of type CustomEvent.

Fired when the drawer opens.

esp-menu-drawer-presented

esp-menu-drawer-presented is of type CustomEvent.

Fired once the drawer's popover is on the top layer, so an opener can stack its own control above it.

esp-menu-drawer-closed

esp-menu-drawer-closed is of type CustomEvent.

Fired when the drawer closes.

CSS Properties

<esp-menu> has the following CSS properties:

--esp-menu-background

Background color of vertical and drawer menus.

--esp-menu-border-color

Border color of menu rails and drawers.

--esp-menu-horizontal-justify-content

Main-axis alignment for horizontal menu items. Defaults to flex-start.

--esp-menu-scrim-color

Scrim color when the drawer is open.

--esp-menu-drawer-shadow

Box shadow for the drawer overlay.

--esp-menu-drawer-width

Drawer width. Defaults to min(22rem, 86vw).

--esp-menu-drawer-item-font-size

Item label size in the full-screen drawer. Defaults to var(--esp-type-large).

--esp-menu-drawer-transition-duration

Duration of the full-screen drawer's transition. Defaults to 0.3s; reduced motion disables it.

--esp-menu-drawer-brand-logo-size

Logo height of the brand centered in the full-screen drawer. Defaults to calc(3 * var(--esp-size-medium)).

--esp-menu-drawer-brand-color

Text and logo color of the full-screen drawer's brand. Defaults to the mirrored brand color, then var(--esp-color-headings).

--esp-menu-top-offset

Top offset for drawers below fixed headers.

--esp-field-background

Background color of the shared field shell. Defaults to var(--esp-color-layer-2).

--esp-field-border-color

Border color of the shared field shell. Defaults to var(--esp-color-border).

--esp-field-border-width

Border width of the shared field shell. Defaults to 1px.

--esp-field-text-color

Text color used inside the shared field shell. Defaults to var(--esp-color-text).

--esp-field-hover-bg

Hover background color of the shared field shell. Derived from --esp-field-background.

--esp-field-focus-bg

Focus background color of the shared field shell. Derived from --esp-field-background.

--esp-field-focus-shadow

Shadow color used for shared field focus treatment. Defaults to var(--esp-color-shadow).

Components API Guides Getting started Styling Espalier Browser support GitHub npm package Taproot I/O