Skip to content

Menus & navigation

All menus share one MenuItem model (label, icon, command, url, items, separator, shortcut). They follow the WAI-ARIA menu and menubar patterns, with type-ahead and arrow keys that mirror in right-to-left layouts.

10 components on this page. Every demo is live — change the theme in the header or flip a demo to right-to-left with its RTL button. 9 of them are React-only for now; Vue, Svelte and Angular versions are coming.

TieredMenu Link to TieredMenu

A vertical menu whose items open nested submenus to the side.

Live demo

Inserted: none

Props

PropTypeDescription
model MenuItem[] Items with nested items.
popup boolean Floating mode (same handle as Menu).

Accessibility

TieredMenu keyboard support
KeyAction
Arrow Down / Arrow Up Next / previous item
Home / End First / last item
Enter / Space Activate the item
Escape Close and return focus to the trigger
Arrow Right / Arrow Left Open / close a submenu (mirrored in RTL)

Code

ReactComing to Vue, Svelte and Angular.

TieredMenu · React
<TieredMenu aria-label="Insert" model={[
  { label: 'Media', items: [{ label: 'Image' }, { label: 'Video' }] },
  { label: 'Table', items: [{ label: '2 × 2' }, { label: '3 × 3' }] },
]} />

ContextMenu Link to ContextMenu

A menu that opens on right-click (or the context-menu key) over a target area.

Live demo
📄 report.pdf — right-click here (or focus and press Shift+F10)

Last command: none

Props

PropTypeDescription
model MenuItem[] Items.
targetRef RefObject<HTMLElement> Element that opens the menu.
ref.show(event) ContextMenuHandle Open programmatically.
onShow / onHide () => void Callbacks.

Accessibility

ContextMenu keyboard support
KeyAction
Shift + F10 / Menu key Open the menu for the focused target
Arrow Down / Arrow Up Next / previous item
Home / End First / last item
Enter / Space Activate the item
Escape Close and return focus to the trigger

Code

ReactComing to Vue, Svelte and Angular.

ContextMenu · React
const area = useRef<HTMLDivElement>(null);
<div ref={area} tabIndex={0}>Right-click me</div>
<ContextMenu targetRef={area} aria-label="File actions"
  model={[{ label: 'Rename' }, { label: 'Duplicate' }, { label: 'Delete', danger: true }]} />

MegaMenu Link to MegaMenu

Large dropdown panels arranged in columns, for sites with many destinations.

Live demo

Picked: none

Props

PropTypeDescription
model MegaMenuItem[] Top items; items is an array of columns (MenuItem[][]).
orientation 'horizontal' | 'vertical' Layout.

Accessibility

MegaMenu keyboard support
KeyAction
Arrow Left / Arrow Right Move between top items
Arrow Down / Arrow Up Move within a panel
Escape Close the panel

Code

ReactComing to Vue, Svelte and Angular.

MegaMenu · React
<MegaMenu aria-label="Products" model={[
  { label: 'Products', items: [
    [{ label: 'Components', items: [{ label: 'Forms' }, { label: 'Charts' }] }],
    [{ label: 'Resources', items: [{ label: 'Docs' }, { label: 'Blog' }] }],
  ] },
]} />

PanelMenu Link to PanelMenu

An accordion-style navigation menu with nested groups.

Live demo

Opened: none

Props

PropTypeDescription
model MenuItem[] Groups with nested items.
multiple boolean Allow several groups open.
defaultExpandedKeys string[] Initially open groups (by item key).

Accessibility

PanelMenu keyboard support
KeyAction
Arrow Down / Arrow Up Move between items
Arrow Right / Arrow Left Expand / collapse a group
Home / End First / last item
Enter / Space Activate

Code

ReactComing to Vue, Svelte and Angular.

PanelMenu · React
<PanelMenu aria-label="Settings" multiple model={[
  { key: 'account', label: 'Account', items: [{ label: 'Profile' }, { label: 'Security' }] },
  { key: 'billing', label: 'Billing', items: [{ label: 'Invoices' }] },
]} />

Dock Link to Dock

A macOS-style launcher with icon magnification.

Live demo

Launched: none

Props

PropTypeDescription
model MenuItem[] Items; icon is required, label is the accessible name.
position 'bottom' | 'top' | 'start' | 'end' Edge.
magnification boolean Enlarge hovered / focused items (off under reduced motion).

Accessibility

Dock keyboard support
KeyAction
Tab Move between items
Enter Activate

A labelled navigation landmark; icons are hidden and each item is named by its label.

Code

ReactComing to Vue, Svelte and Angular.

Dock · React
<Dock aria-label="Apps" model={[
  { label: 'Finder', icon: '📁' }, { label: 'Mail', icon: '✉️' }, { label: 'Music', icon: '🎵' },
]} />

SplitButton Link to SplitButton

A primary action with a menu of related secondary actions.

Live demo

Last action: none

Props

PropTypeDescription
label / onClick ReactNode / handler Main action.
model MenuItem[] Secondary actions.
variant / size ButtonVariant / ButtonSize Same as Button.
menuButtonLabel string Accessible name of the arrow button.

Accessibility

SplitButton keyboard support
KeyAction
Enter / Space Run the main action
Arrow Down (on the arrow button) Open the menu

Code

ReactComing to Vue, Svelte and Angular.

SplitButton · React
<SplitButton label="Save" onClick={save} model={[
  { label: 'Save as draft', command: saveDraft },
  { label: 'Save and publish', command: publish },
]} />

SpeedDial Link to SpeedDial

A floating action button that fans out related actions in a line or circle.

Live demo

Created: none

Props

PropTypeDescription
model MenuItem[] Actions (icon + label).
direction 'up' | 'down' | 'start' | 'end' | … Line direction.
type 'linear' | 'circle' | 'semi-circle' | 'quarter-circle' Layout.
radius number Radius for circular types.

Accessibility

SpeedDial keyboard support
KeyAction
Enter / Space Open / close
Arrow keys Move between actions
Escape Close and focus the button

Code

ReactComing to Vue, Svelte and Angular.

SpeedDial · React
<SpeedDial aria-label="Create" direction="up" model={[
  { label: 'Note', icon: '📝' }, { label: 'Photo', icon: '📷' }, { label: 'Link', icon: '🔗' },
]} />

Search Pelagic UI