dropdown-wc

Accessible dropdown menus with keyboard navigation, focus management, and automatic positioning.

Overview

The <dropdown-wc> component provides an accessible dropdown menu. It handles all keyboard interactions (arrow keys, Escape, Enter), click-outside-to-close, and proper ARIA attributes.

<dropdown-wc> <button data-trigger>Options</button> <menu> <li><button>Edit</button></li> <li><button>Duplicate</button></li> <li><button>Share</button></li> <li role="separator"></li> <li><button class="danger">Delete</button></li> </menu> </dropdown-wc>

Attributes

Attribute Values Default Description
data-position bottom-start, bottom-end, top-start, top-end bottom-start Menu position relative to trigger
data-open boolean - Reflected attribute indicating open state

Keyboard Navigation

Full keyboard support following WAI-ARIA menu pattern:

Key Action
Enter / Space Open menu (on trigger) or activate item (in menu)
ArrowDown Open menu and focus first item, or move to next item
ArrowUp Open menu and focus last item, or move to previous item
Home Focus first menu item
End Focus last menu item
Escape Close menu and return focus to trigger
Tab Close menu and move focus to next element

Position Variants

Control menu alignment with the data-position attribute.

<dropdown-wc data-position="bottom-end"> <button data-trigger>Bottom End</button> <menu>...</menu> </dropdown-wc>

Menu with Separators

Use role="separator" on empty list items to create visual dividers.

Destructive Actions

Add the danger class to highlight destructive actions.

<li><button class="danger">Delete permanently</button></li>

With Links

Menu items can be links instead of buttons for navigation.

JavaScript API

Control the dropdown programmatically:

const dropdown = document.querySelector('dropdown-wc'); // Methods dropdown.open(); // Open the menu dropdown.close(); // Close the menu dropdown.toggle(); // Toggle open/closed // Properties dropdown.isOpen; // Boolean: current state // Events dropdown.addEventListener('dropdown-open', () => { console.log('Menu opened'); }); dropdown.addEventListener('dropdown-close', () => { console.log('Menu closed'); });

Accessibility

  • Trigger has aria-haspopup="menu" and aria-expanded
  • Menu has role="menu"
  • Menu items have role="menuitem"
  • Separators have role="separator"
  • Full keyboard navigation per WAI-ARIA menu pattern
  • Focus returns to trigger on close
  • Click outside or Escape closes menu