drop-down
Accessible dropdown menus with keyboard navigation, focus management, and automatic positioning.
Overview
The <drop-down> component provides an accessible dropdown menu. It handles all keyboard interactions (arrow keys, Escape, Enter), click-outside-to-close, and proper ARIA attributes.
Basic dropdown menu structure
<drop-down> <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></drop-down>
Attributes
| Attribute | Values | Default | Description |
|---|---|---|---|
position | "bottom-start", "bottom-end", "top-start", "top-end" | bottom-start | Menu position relative to trigger |
hover | boolean | — | Open on hover/focus instead of click (useful for nav menus) |
no-flip | boolean | — | Disable automatic flip when menu overflows viewport |
open (reflected) | boolean | — | Reflected state — set by open()/close()/toggle() methods, not intended as initial markup |
Required Structure
| Element | Required | Description |
|---|---|---|
<button data-trigger> or <a data-trigger> | yes | Trigger element that opens the menu |
<menu> | yes | Menu container with <li> items holding <button> or <a> actions |
Child Attributes
| Attribute | On | Values | Description |
|---|---|---|---|
data-trigger | button | a | boolean | Marks the element that opens the menu. Falls back to first <button> if absent. |
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 position attribute.
Dropdown with position attribute
<drop-down position="bottom-end"> <button data-trigger>Bottom End</button> <menu>...</menu></drop-down>
Menu with Separators
Use role="separator" on empty list items to create visual dividers.
Destructive Actions
Add the danger class to highlight destructive actions.
Destructive action button
<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:
Dropdown JavaScript API
const dropdown = document.querySelector('drop-down'); // Methodsdropdown.open(); // Open the menudropdown.close(); // Close the menudropdown.toggle(); // Toggle open/closed // Propertiesdropdown.isOpen; // Boolean: current state // Eventsdropdown.addEventListener('drop-down:open', () => { console.log('Menu opened');}); dropdown.addEventListener('drop-down:close', () => { console.log('Menu closed');});
Accessibility
- Trigger has
aria-haspopup="menu"andaria-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