Component

Dropdown

Published on

Description Link to section description

The Dropdown component displays a list of links behind a toggle button. It uses the native HTML popover attribute with popovertarget for the button and CSS anchor positioning for placement, so it requires no JavaScript. The button label is set with the label prop, or replaced entirely with a button snippet for icon-only triggers. Remaining props are applied to the button; add class="chevron" for a chevron that rotates while open. The children snippet is the list itself.

In browsers without CSS anchor positioning the dropdown still opens, closes, and light-dismisses; it renders at its position in the normal flow after the button, without collision avoidance.

Example Link to section example

Open in new tab(opens in new tab)
View HTML markup
<nav aria-label="Primary">
  <div><button type="button" popovertarget="dropdown-nav" class="chevron">Products</button>
    <div id="dropdown-nav" popover="auto" class="ds-dropdown">
      <ul>
        <li><a href="#">Analytics</a></li>
        <li><a href="#">Automation</a></li>
        <li><a href="#">Reports</a></li>
      </ul>
    </div>
  </div>
</nav>
Open in new tab(opens in new tab)
View HTML markup
<ul>
  <li class="ds-item" id="item-1"><a href="#">Step 1</a> <strong><span>Complete</span></strong>
    <div><button type="button" popovertarget="item-1-menu"><svg class="icon" aria-hidden="true">
          <use href="/img/icons.svg#dots"></use>
        </svg><span class="visually-hidden">Actions for Step 1</span></button>
      <div id="item-1-menu" popover="auto" class="ds-dropdown">
        <ul>
          <li><a href="#">Edit</a></li>
          <li><a href="#">Duplicate</a></li>
          <li><a href="#">Archive</a></li>
        </ul>
      </div>
    </div>
  </li>
  <li class="ds-item" id="item-2"><a href="#">Step 2</a> <strong class="inprogress"><span>In progress</span></strong>
    <div><button type="button" popovertarget="item-2-menu"><svg class="icon" aria-hidden="true">
          <use href="/img/icons.svg#dots"></use>
        </svg><span class="visually-hidden">Actions for Step 2</span></button>
      <div id="item-2-menu" popover="auto" class="ds-dropdown">
        <ul>
          <li><a href="#">Edit</a></li>
          <li><a href="#">Duplicate</a></li>
          <li><a href="#">Archive</a></li>
        </ul>
      </div>
    </div>
  </li>
  <li class="ds-item" id="item-3"><a href="#">Step 3</a> <strong class="incomplete"><span>Not yet started</span></strong>
    <div><button type="button" popovertarget="item-3-menu"><svg class="icon" aria-hidden="true">
          <use href="/img/icons.svg#dots"></use>
        </svg><span class="visually-hidden">Actions for Step 3</span></button>
      <div id="item-3-menu" popover="auto" class="ds-dropdown">
        <ul>
          <li><a href="#">Edit</a></li>
          <li><a href="#">Duplicate</a></li>
          <li><a href="#">Archive</a></li>
        </ul>
      </div>
    </div>
  </li>
</ul>

Accessibility Link to section accessibility

  • This is the WAI disclosure navigation pattern: a button plus a plain list of links, not role="menu", which would require JavaScript arrow-key handling.
  • The browser sets aria-expanded on the popovertarget button automatically.
  • Escape and light-dismiss close the dropdown, returning focus to the button.
  • The list follows the button in source order, so Tab moves from the button into the links.
  • Icon-only triggers must include a .visually-hidden label inside the button snippet.
  • Never place a dropdown inside a larger click target. Rows that carry a dropdown use ItemList rather than a clickable Task list row, so a near-miss on the button cannot navigate away.

References Link to section references

  • Popover — the underlying overlay primitive
  • Item list — non-clickable rows with a per-row dropdown
  • Disclosure — for inline expandable content

Variables Link to section variables

None