Menu
Displays a menu to the user, such as a set of actions or functions, triggered by a button.
<NaviusMenu>
<NaviusMenuTrigger class="... data-[popup-open]:bg-accent">
Options
</NaviusMenuTrigger>
<NaviusMenuPositioner Side="bottom" Align="start" SideOffset="6">
<NaviusMenuPopup class="... bg-popover text-popover-foreground shadow-md
data-[open]:animate-in data-[closed]:animate-out">
<NaviusMenuGroupLabel class="...">My Account</NaviusMenuGroupLabel>
<NaviusMenuItem class="... data-[highlighted]:bg-accent">
New Tab <span class="...">⌘T</span>
</NaviusMenuItem>
<NaviusMenuItem class="...">New Window</NaviusMenuItem>
<NaviusMenuSub>
<NaviusMenuSubTrigger class="... data-[popup-open]:bg-accent">
More Tools
</NaviusMenuSubTrigger>
<NaviusMenuSubContent class="...">
<NaviusMenuItem>Save Page As…</NaviusMenuItem>
<NaviusMenuItem>Developer Tools</NaviusMenuItem>
</NaviusMenuSubContent>
</NaviusMenuSub>
<NaviusMenuSeparator class="-mx-1 my-1 h-px bg-border" />
<NaviusMenuCheckboxItem @bind-Checked="_showBookmarks" class="...">
<NaviusMenuItemIndicator>✓</NaviusMenuItemIndicator>
Show Bookmarks
</NaviusMenuCheckboxItem>
<NaviusMenuSeparator class="-mx-1 my-1 h-px bg-border" />
<NaviusMenuRadioGroup @bind-Value="_person">
<NaviusMenuRadioItem Value="pedro" class="...">
<NaviusMenuItemIndicator>•</NaviusMenuItemIndicator>
Pedro Duarte
</NaviusMenuRadioItem>
<NaviusMenuRadioItem Value="colm" class="...">
<NaviusMenuItemIndicator>•</NaviusMenuItemIndicator>
Colm Tuite
</NaviusMenuRadioItem>
</NaviusMenuRadioGroup>
<NaviusMenuArrow class="fill-popover" />
</NaviusMenuPopup>
</NaviusMenuPositioner>
</NaviusMenu>
@code {
private bool? _showBookmarks = true;
private string? _person = "pedro";
}Features
- Can be controlled (
@bind-Open) or uncontrolled (DefaultOpen). - Supports submenus with their own independent open state.
- Supports items, group labels, separators, checkbox items and radio groups.
- Full keyboard navigation with roving focus and typeahead.
- Focus is fully managed: opening focuses the first item, closing returns focus to the trigger.
- Dismisses on Escape, outside pointer-down, and selecting an item (cancelable via
OnSelect). - The engine self-portals the Popup to
document.bodyto escape clipping and stacking ancestors. - Direction-aware: flips submenu open/close arrow keys in RTL.
Installation
Reference the Navius.Primitives package for the headless primitive, or vendor a styled version with the CLI: navius add copies the styled zits/ui component plus the brain files it depends on.
navius add dropdown-menuAnatomy
Import the parts and assemble them. The Positioner and Popup replace the former Content; the Popup self-portals.
@using Navius.Primitives.Components.Menu
<NaviusMenu>
<NaviusMenuTrigger />
<NaviusMenuPositioner>
<NaviusMenuPopup>
<NaviusMenuGroupLabel />
<NaviusMenuItem />
<NaviusMenuGroup>
<NaviusMenuGroupLabel />
<NaviusMenuItem />
</NaviusMenuGroup>
<NaviusMenuCheckboxItem>
<NaviusMenuItemIndicator />
</NaviusMenuCheckboxItem>
<NaviusMenuRadioGroup>
<NaviusMenuRadioItem>
<NaviusMenuItemIndicator />
</NaviusMenuRadioItem>
</NaviusMenuRadioGroup>
<NaviusMenuSeparator />
<NaviusMenuSub>
<NaviusMenuSubTrigger />
<NaviusMenuSubContent>
<NaviusMenuItem />
</NaviusMenuSubContent>
</NaviusMenuSub>
<NaviusMenuArrow />
</NaviusMenuPopup>
</NaviusMenuPositioner>
</NaviusMenu>API Reference
Root
Contains all the parts of a menu. Owns the open state and renders no DOM of its own.
| Prop | Type | Default |
|---|---|---|
| Open | bool | false |
| OpenChanged | EventCallback<bool> | - |
| DefaultOpen | bool | false |
| Modal | bool | true |
| Dir | string? | - |
| ChildContent | RenderFragment? | - |
Trigger
The button that toggles the menu. By default it has aria-haspopup, aria-expanded and aria-controls wired to the popup. Renders a button.
| Prop | Type | Default |
|---|---|---|
| Disabled | bool | false |
| ChildContent | RenderFragment? | - |
Data attributes
| Data attribute | Values |
|---|---|
| [data-popup-open] | Present while the menu is open. |
| [data-disabled] | Present when disabled. |
Positioner
Owns placement (side / align / offsets / collision). A flag-setter that publishes the placement options; the Popup renders the positioning element the engine anchors to the trigger and writes data-side / data-align + --anchor-* onto.
| Prop | Type | Default |
|---|---|---|
| Side | string | "bottom" |
| Align | string | "center" |
| SideOffset | double | 0 |
| AlignOffset | double | 0 |
| Flip | bool | true |
| AvoidCollisions | bool | true |
| CollisionPadding | double? | - |
| ArrowPadding | double | 0 |
| ChildContent | RenderFragment? | - |
Popup
The menu surface, self-portaled and anchored to the trigger. Mounted while open (kept mounted through its exit transition). Renders a div with role=menu.
| Prop | Type | Default |
|---|---|---|
| Loop | bool | false |
| KeepMounted | bool | false |
| OnEscapeKeyDown | EventCallback<NaviusEscapeKeyDownEventArgs> | - |
| OnPointerDownOutside | EventCallback<NaviusPointerDownOutsideEventArgs> | - |
| ChildContent | RenderFragment? | - |
Data attributes
| Data attribute | Values |
|---|---|
| [data-open] | Present while the menu is open. |
| [data-closed] | Present while closing (through the exit transition). |
| [data-starting-style] | Present on the first committed open frame. |
| [data-ending-style] | Present while animating out. |
| [data-side] | "top" | "right" | "bottom" | "left" |
| [data-align] | "start" | "center" | "end" |
Arrow
An optional arrow that the positioner keeps pointed at the trigger. Renders an svg.
| Prop | Type | Default |
|---|---|---|
| Width | double | 10 |
| Height | double | 5 |
| ChildContent | RenderFragment? | - |
Item
A selectable menu item. Activates on click or Enter/Space, then closes the menu unless OnSelect prevents it. Renders a div with role=menuitem.
| Prop | Type | Default |
|---|---|---|
| OnSelect | EventCallback<NaviusSelectEventArgs> | - |
| Disabled | bool | false |
| TextValue | string? | - |
| ChildContent | RenderFragment? | - |
Data attributes
| Data attribute | Values |
|---|---|
| [data-highlighted] | Present when the item is the roving-focus target. |
| [data-disabled] | Present when disabled. |
Group
A wrapper that groups related items and is labelled by a GroupLabel child. Renders a div with role=group.
| Prop | Type | Default |
|---|---|---|
| ChildContent | RenderFragment? | - |
GroupLabel
A non-interactive heading. When nested in a Group it labels that group via aria-labelledby. Renders a div.
| Prop | Type | Default |
|---|---|---|
| ChildContent | RenderFragment? | - |
CheckboxItem
An item that can be checked, unchecked or indeterminate. Cascades a state context the ItemIndicator reads. Renders a div with role=menuitemcheckbox.
| Prop | Type | Default |
|---|---|---|
| Checked | bool? | - |
| CheckedChanged | EventCallback<bool?> | - |
| DefaultChecked | bool? | - |
| OnSelect | EventCallback<NaviusSelectEventArgs> | - |
| Disabled | bool | false |
| TextValue | string? | - |
| ChildContent | RenderFragment? | - |
Data attributes
| Data attribute | Values |
|---|---|
| [data-checked] | Present when checked. |
| [data-unchecked] | Present when unchecked. |
| [data-indeterminate] | Present when indeterminate. |
| [data-highlighted] | Present when the item is the roving-focus target. |
| [data-disabled] | Present when disabled. |
RadioGroup
Groups RadioItems and cascades the selected value. Renders a div with role=group.
| Prop | Type | Default |
|---|---|---|
| Value | string? | - |
| ValueChanged | EventCallback<string?> | - |
| DefaultValue | string? | - |
| ChildContent | RenderFragment? | - |
RadioItem
An item inside a RadioGroup; checked when the group's value equals its Value. Cascades a state context the ItemIndicator reads. Renders a div with role=menuitemradio.
| Prop | Type | Default |
|---|---|---|
| Value | string | - |
| OnSelect | EventCallback<NaviusSelectEventArgs> | - |
| Disabled | bool | false |
| TextValue | string? | - |
| ChildContent | RenderFragment? | - |
Data attributes
| Data attribute | Values |
|---|---|
| [data-checked] | Present when checked. |
| [data-unchecked] | Present when unchecked. |
| [data-highlighted] | Present when the item is the roving-focus target. |
| [data-disabled] | Present when disabled. |
ItemIndicator
Renders the check or dot glyph for a CheckboxItem or RadioItem. Present only when the parent is checked (or indeterminate). Renders a span.
| Prop | Type | Default |
|---|---|---|
| ForceMount | bool | false |
| ChildContent | RenderFragment? | - |
Separator
A visual divider between items or groups. Renders a div with role=separator.
| Prop | Type | Default |
|---|---|---|
| Attributes | IDictionary<string, object>? | - |
Sub
Contains the parts of a submenu. Owns its own nested open state and renders no DOM of its own.
| Prop | Type | Default |
|---|---|---|
| Open | bool | false |
| OpenChanged | EventCallback<bool> | - |
| DefaultOpen | bool | false |
| ChildContent | RenderFragment? | - |
SubTrigger
An item inside the parent menu that opens a submenu on hover, ArrowRight (ArrowLeft in RTL) and Enter/Space. Anchors the submenu. Renders a div with role=menuitem.
| Prop | Type | Default |
|---|---|---|
| Disabled | bool | false |
| TextValue | string? | - |
| ChildContent | RenderFragment? | - |
Data attributes
| Data attribute | Values |
|---|---|
| [data-popup-open] | Present while the submenu is open. |
| [data-highlighted] | Present when the item is the roving-focus target. |
| [data-disabled] | Present when disabled. |
SubContent
The floating submenu surface, self-portaled and positioned to the side of the SubTrigger. ArrowLeft (ArrowRight in RTL) and Escape close only this submenu. Renders a div with role=menu.
| Prop | Type | Default |
|---|---|---|
| SideOffset | double | 0 |
| AlignOffset | double | 0 |
| Loop | bool | false |
| ForceMount | bool | false |
| ChildContent | RenderFragment? | - |
Data attributes
| Data attribute | Values |
|---|---|
| [data-open] | Present while the submenu is open. |
| [data-closed] | Present while closing (through the exit transition). |
Accessibility
Implements the roles, states, and keyboard map of the menu button WAI-ARIA APG pattern. Behavior is covered by the browser test suite and an axe-core WCAG gate in CI.
Keyboard interactions
| Key | Description |
|---|---|
| Space | When focus is on the trigger, opens the menu and focuses the first item. When on an item, activates it. |
| Enter | When focus is on the trigger, opens the menu and focuses the first item. When on an item, activates it. On a SubTrigger, opens the submenu and focuses its first item. |
| ArrowDown | When focus is on the trigger, opens the menu. When inside, moves focus to the next item. |
| ArrowUp | When focus is on the trigger, opens the menu. When inside, moves focus to the previous item. |
| ArrowRight | On a SubTrigger, opens its submenu and focuses the first item (ArrowLeft in RTL). |
| ArrowLeft | Inside a submenu, closes it and returns focus to the SubTrigger (ArrowRight in RTL). |
| Esc | Closes the menu (or the current submenu) and returns focus to the trigger. |
| Tab | Items are not in the tab sequence; focus is managed with a roving tabindex. |