Dropdown Menu
Description
Section titled “Description”.bp-dropdown is a custom element (<bp-dropdown>) that wires keyboard navigation, focus management, and open/close state. CSS handles all visual appearance via [data-open]. The panel is a <ul> of <button> or <a> items.
Basic dropdown
<bp-dropdown class="bp-dropdown"><button class="bp-btn bp-btn--outline bp-dropdown__trigger"> Options ▾</button><ul class="bp-dropdown__panel" role="menu"> <li><button class="bp-dropdown__item" role="menuitem">Edit</button></li> <li><button class="bp-dropdown__item" role="menuitem">Duplicate</button></li> <li><div class="bp-dropdown__separator" role="separator"></div></li> <li><button class="bp-dropdown__item bp-dropdown__item--danger" role="menuitem">Delete</button></li></ul></bp-dropdown>With icons
<bp-dropdown class="bp-dropdown"><button class="bp-btn bp-btn--primary bp-dropdown__trigger"> Actions ▾</button><ul class="bp-dropdown__panel" role="menu"> <li> <a href="#" class="bp-dropdown__item" role="menuitem"> <svg class="bp-dropdown__icon" viewBox="0 0 16 16" fill="currentColor"> <path d="M11.013 1.427a1.75 1.75 0 0 1 2.474 0l1.086 1.086a1.75 1.75 0 0 1 0 2.474l-8.61 8.61c-.21.21-.47.364-.756.445l-3.251.93a.75.75 0 0 1-.927-.928l.929-3.25c.081-.286.235-.547.445-.758l8.61-8.61Z"/> </svg> Edit </a> </li> <li> <button class="bp-dropdown__item" role="menuitem"> <svg class="bp-dropdown__icon" viewBox="0 0 16 16" fill="currentColor"> <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"/> <path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"/> </svg> Duplicate </button> </li> <li><div class="bp-dropdown__separator" role="separator"></div></li> <li> <button class="bp-dropdown__item bp-dropdown__item--danger" role="menuitem"> <svg class="bp-dropdown__icon" viewBox="0 0 16 16" fill="currentColor"> <path d="M11 1.75V3h2.25a.75.75 0 0 1 0 1.5H2.75a.75.75 0 0 1 0-1.5H5V1.75C5 .784 5.784 0 6.75 0h2.5C10.216 0 11 .784 11 1.75ZM4.496 6.675l.66 6.6a.25.25 0 0 0 .249.225h5.19a.25.25 0 0 0 .249-.225l.66-6.6a.75.75 0 0 1 1.492.149l-.66 6.6A1.748 1.748 0 0 1 10.595 15h-5.19a1.75 1.75 0 0 1-1.741-1.575l-.66-6.6a.75.75 0 1 1 1.492-.15Z"/> </svg> Delete </button> </li></ul></bp-dropdown>JavaScript
Section titled “JavaScript”The <bp-dropdown> custom element is required for keyboard navigation. Load it once:
<script type="module" src="https://unpkg.com/@be-partner-labs/ds/js/bp-dropdown.esm.min.js"></script>Or via npm:
import '@be-partner-labs/ds/js/bp-dropdown'What JS handles:
- Opens/closes panel on trigger click, sets
[data-open] - Arrow Up/Down moves focus between items
- Home/End jumps to first/last item
- Escape closes and returns focus to trigger
- Click outside closes the panel
What CSS handles: All visual appearance via [data-open] on the wrapper.
Public API
Section titled “Public API”| Variable | Default | Description |
|---|---|---|
--dropdown-bg | --bp-color-bg-elevated | Panel background |
--dropdown-border | 1px solid --bp-color-border | Panel border |
--dropdown-radius | --bp-radius-lg | Panel border radius |
--dropdown-shadow | --bp-shadow-lg | Panel shadow |
--dropdown-min-width | 12rem | Minimum panel width |
--dropdown-item-gap | --bp-space-2 --bp-space-3 | Item padding |
✓ No axe violations tested 2026-05-11
WCAG criteria covered:
Accessibility
Section titled “Accessibility”- Use
<ul role="menu">for the panel androle="menuitem"on each item. - The trigger gets
aria-haspopup="true"andaria-expandedwired automatically. - Keyboard pattern follows ARIA Menu Button: Arrow keys navigate items, Escape closes, Tab closes without returning focus.
- Disabled items: use
aria-disabled="true"on.bp-dropdown__item— they are skipped in keyboard navigation. - For navigation links (not actions), use
<a>items instead of<button>— the keyboard behavior is the same.
Browser APIs
Section titled “Browser APIs”| API | Availability | Used for | Without it |
|---|---|---|---|
| Custom Elements | Widely available Baseline 2020 | <bp-dropdown> keyboard wiring | Menu opens/closes only on click, no keyboard nav |
visibility + opacity transition | Widely available Baseline 2012 | Smooth open/close | Instant show/hide |
Internals
Section titled “Internals”State lives entirely in [data-open] on <bp-dropdown>. The custom element sets and removes this attribute; CSS reads it. Keyboard navigation uses a roving focus pattern — focus() is called directly on items, no tabindex changes needed since items are naturally focusable <button> or <a> elements.