Menu

The Menu component provides a dropdown menu with items that support keyboard navigation. It consists of two elements: el-dm-menu for the container and el-dm-menu-item for individual items.

Installation

npm install @duskmoon-dev/el-menu

Usage

import '@duskmoon-dev/el-menu/register';
<el-dm-menu id="my-menu">
  <el-dm-button slot="trigger" onclick="this.parentElement.toggle()">
    Open Menu
  </el-dm-button>
  <el-dm-menu-item value="edit">Edit</el-dm-menu-item>
  <el-dm-menu-item value="duplicate">Duplicate</el-dm-menu-item>
  <el-dm-menu-item value="delete">Delete</el-dm-menu-item>
</el-dm-menu>

Live Demo

Menu Demo

Actions

View DetailsEditDuplicate
ArchiveDelete
PropertyTypeDefaultDescription
openbooleanfalseWhether the menu is open
anchorstring-Element ref or CSS selector for anchor element
placementMenuPlacement'bottom-start'Menu placement relative to trigger

Placement Options

type MenuPlacement =
  | 'top' | 'top-start' | 'top-end'
  | 'bottom' | 'bottom-start' | 'bottom-end'
  | 'left' | 'right';
MethodDescription
show()Opens the menu
hide()Closes the menu
toggle()Toggles the menu open/closed
EventDetailDescription
open-Fired when menu opens
close-Fired when menu closes
select{ value: string }Fired when an item is selected

Event Handling

const menu = document.querySelector('el-dm-menu');

menu.addEventListener('select', (e) => {
  console.log('Selected:', e.detail.value);
});

menu.addEventListener('open', () => {
  console.log('Menu opened');
});

menu.addEventListener('close', () => {
  console.log('Menu closed');
});
PropertyTypeDefaultDescription
valuestring-Value associated with the item
disabledbooleanfalseWhether the item is disabled

Placement Examples

<el-dm-menu placement="bottom-start">...</el-dm-menu>
<el-dm-menu placement="bottom-end">...</el-dm-menu>
<el-dm-menu placement="top">...</el-dm-menu>
<el-dm-menu placement="right">...</el-dm-menu>

Menu Placements

Bottom Start

Option 1Option 2

Bottom End

Option 1Option 2
<el-dm-menu>
  <el-dm-button slot="trigger" onclick="this.parentElement.toggle()">
    File
  </el-dm-button>
  <el-dm-menu-item value="new">
    <svg slot="icon">...</svg>
    New File
  </el-dm-menu-item>
  <el-dm-menu-item value="open">
    <svg slot="icon">...</svg>
    Open
  </el-dm-menu-item>
</el-dm-menu>

Use a <div role="separator"> to create visual separation between menu item groups:

<el-dm-menu>
  <el-dm-menu-item>Cut</el-dm-menu-item>
  <el-dm-menu-item>Copy</el-dm-menu-item>
  <el-dm-menu-item>Paste</el-dm-menu-item>
  <div role="separator"></div>
  <el-dm-menu-item>Delete</el-dm-menu-item>
</el-dm-menu>
SlotDescription
triggerTrigger element to open the menu
defaultMenu items
SlotDescription
iconIcon before the content
defaultItem content

CSS Parts (Menu)

PartDescription
menuThe menu container
itemsThe menu items wrapper

CSS Parts (Menu Item)

PartDescription
itemThe menu item container
iconThe icon wrapper
contentThe content wrapper

Accessibility

  • Uses role="menu" for the container and role="menuitem" for items
  • Full keyboard navigation: Arrow keys, Home, End, Enter, Space, Escape
  • Disabled items have aria-disabled="true"
  • Menu has aria-hidden when closed
  • Focus is automatically moved to the first item when opened
  • Tab key closes the menu