Skip to content

Dropdown

A button that opens a short menu of actions or choices. For picking a value inside a form, use the native select in a text field instead.

CSS
css/components/dropdown.css
JS
js/components/dropdown.js

01 — Variants

Choice

One choice from a few, shown in the button with data-label-from-choice.

Actions

A menu of actions, lined up with the button’s right edge (data-align="end"). A divider separates the destructive one.

02 — Behavior

Script

NameDetail
Itemsmenuitem, menuitemradio (one checked) or menuitemcheckbox (toggles). aria-disabled="true" disables one.
KeyboardEnter, Space or ↓ opens; ↑ ↓ Home End move; letters jump; Esc closes and returns focus.
PlacementOpens in the top layer, so no panel clips it, and flips above the button when there’s no room below.
jewel:selectDetail { item, value }.

03 — Usage

Use it for

  • Sorting, view options and actions on one item.
  • Up to about eight items.

Avoid

  • Picking a value in a form. Use a select.
  • Navigation. Use links in the header or side nav.
  • Long lists. Use search.

04 — Accessibility

Notes

  • Follows the ARIA menu button pattern; the trigger keeps aria-expanded in step.
  • Focus moves into the menu when it opens and back to the button when it closes.

05 — Without Jewel’s JS

What the script does

The script opens and closes the menu, moves focus through it from the keyboard and keeps checked items in step. The CSS reads only the markup below, so a framework can set it itself and leave out dropdown.js and data-component.

StateSet thisNotes
OpenRemove hidden from .dropdown__menu; aria-expanded="true" on .dropdown__triggerTurns the chevron. The trigger also carries aria-haspopup="menu" and aria-controls with the menu’s id.
Itemstabindex="-1" on every [role^="menuitem"]Focus moves with the arrow keys, not Tab.
Checkedaria-checked="true" on a menuitemradio or menuitemcheckboxDraws the tick. Only one radio in a menu is checked.
Disabledaria-disabled="true" on an itemDims it. Ignore its clicks and skip it with the keys.
Placementdata-align="end" or data-side="top" on .dropdownCSS puts the menu under the trigger. The script lifts it into the top layer instead (popover, .is-floating, fixed top and left), so a panel can’t clip it.
Choice in the labelThe chosen radio’s text in the trigger: “Sort: Newest”Replaces data-label-from-choice.

Events and keyboard

  • Enter, Space or ↓ on the trigger opens the menu with focus on the checked item, or the first; ↑ opens it on the last.
  • In the menu, ↑ ↓ move and wrap, Home and End jump, and typed letters jump to the first item that starts with them.
  • Enter or Space chooses. A menuitemcheckbox keeps the menu open; anything else closes it and returns focus to the trigger.
  • Esc closes and returns focus to the trigger. Tab, or a press outside, closes it without moving focus.
  • jewel:select doesn’t fire without the script.