⚠️ Design system CSS not found. Check the path in cms/docs.config.js → designSystemPath, then re-run npm run docgen.

Dropdown

Contextual menus and action lists

Design System / Dropdown
Download .md file
Open .md in new tab

Dropdowns show a contextual menu when a trigger is clicked. They are the universal menu pattern — used in the site header, sticky bars, tool toolbars, and page content. One component, same classes everywhere.


Trigger patterns

The trigger is the element that opens the dropdown. provides built-in styling — no additional classes needed.

Icon + text + chevron

The most common trigger. The rotates 180 degrees when the dropdown is open.

<div class="dropdown">
  <button class="dropdown-trigger" type="button" aria-haspopup="true" aria-expanded="false">
    <div class="svg-icn" data-icon="user"><!-- svg --></div>
    <span>Account</span>
    <div class="svg-icn dropdown-chevron" data-icon="chevron-down"><!-- svg --></div>
  </button>
  <div class="dropdown-menu">
    <!-- items -->
  </div>
</div>

Icon-only trigger

For toolbars and compact contexts. No text, no chevron — the icon alone signals "click for options."

<button class="dropdown-trigger" type="button" aria-haspopup="true" aria-expanded="false" aria-label="More options">
  <div class="svg-icn" data-icon="more-horizontal"><!-- svg --></div>
</button>

Button trigger

For page content where the trigger should look like a standard button.

<button class="dropdown-trigger button" data-variant="outline" type="button" ...>
  Options
  <div class="svg-icn dropdown-chevron"><!-- chevron svg --></div>
</button>

When to use a chevron

Scenario Chevron? Why
Selector-style trigger (choosing a value) Yes Signals "pick from a list"
Navigation dropdown (Account, Profile) Yes Shows the menu expands downward
Icon-only trigger (⋯ more, settings gear) No The icon itself implies a menu
Button trigger with label Optional Use when the button looks like a selector

Menu alignment

Menus open left-aligned by default. Add to right-align from the trigger.

<div class="dropdown-menu is-right">

Use when the dropdown is near the right edge of the viewport to prevent overflow.


Item patterns

Text-only item

The simplest item — just a label with no icon.

<button class="dropdown-item" role="menuitem" type="button">Admin</button>

Icon-left item

An icon before the text reinforces the action. Use for action verbs like Edit, Download, Delete.

<button class="dropdown-item" role="menuitem" type="button">
  <div class="svg-icn" data-icon="settings"><!-- svg --></div>
  <span>Settings</span>
</button>

Icon-right item (trailing content)

Use to push trailing content to the right edge. Ideal for keyboard shortcuts, badges, status indicators, or chevrons hinting at sub-menus.

<button class="dropdown-item" role="menuitem" type="button">
  <span>Undo</span>
  <span class="dropdown-item-end"><kbd>Ctrl+Z</kbd></span>
</button>

Item with description

Use for supporting text below the label.

<button class="dropdown-item" role="menuitem" type="button">
  <div>
    <div>From template</div>
    <div class="dropdown-desc">Choose from pre-built project templates</div>
  </div>
</button>

Avatar item

For user menus showing the logged-in user's identity.

E
Erlen Masson
erlen@bydefault.studio

Section labels

Use to create non-interactive section headers that group items.

Actions
Danger zone
<div class="dropdown-label">Actions</div>
<button class="dropdown-item" role="menuitem" type="button">Rename</button>
...
<div class="dropdown-divider" role="separator"></div>
<div class="dropdown-label">Danger zone</div>
<button class="dropdown-item dropdown-item--danger" role="menuitem" type="button">Delete project</button>

Disabled item

<button class="dropdown-item is-disabled" role="menuitem" type="button" disabled aria-disabled="true">
  Save as...
</button>

When to use what

Pattern When to use Example
Icon-left Action verbs — the icon reinforces what the action does Edit, Download, Delete, Settings
Icon-right () Trailing metadata — keyboard shortcuts, badges, status Undo Ctrl+Z, Status Active
No icon Simple value selection — the text is self-explanatory Role names, client names, sizes
Avatar User identification — profile menus Account dropdown
Description () Items that need explanation "From template — Choose from pre-built..."
Section label () Grouping related items under a heading "Switch Role", "Danger zone"
Divider () Separating logical groups Between actions and danger items

JavaScript

Include assets/js/dropdown.js on any page. It auto-initialises all elements — no setup needed.

<script src="/assets/js/dropdown.js"></script>

Clicking a toggles on the parent . Clicking outside or pressing Escape closes all open dropdowns.


Keyboard interactions

Key Action
Enter / Space Opens the dropdown (on trigger), activates item (on item)
ArrowDown Moves focus to the next item
ArrowUp Moves focus to the previous item
Escape Closes the dropdown and returns focus to the trigger
Tab Moves focus out of the dropdown

Accessibility

  • Trigger: aria-haspopup="true", aria-expanded="false" (JS updates to "true" on open)
  • Icon-only triggers: add aria-label describing the action
  • Menu: role="menu"
  • Items: role="menuitem" on buttons, or just <a> for link items
  • Dividers: role="separator"
  • Disabled items: disabled attribute + aria-disabled="true"

Structure reference

Element Class Purpose
Container Positioning context
Trigger Clickable element that opens the menu
Chevron Rotating arrow indicator (on trigger)
Menu The panel that appears
Menu (right) .dropdown-menu .is-right Right-aligned from trigger
Item Clickable row
Item (danger) .dropdown-item .dropdown-item--danger Destructive action
Item (disabled) .dropdown-item .is-disabled Unavailable action
Trailing content Right-aligned metadata inside an item
Description Supporting text under item label
Label Non-interactive section header
Divider Separator line between groups

Usage rules

Do:

  • Use dropdowns for contextual actions and selections
  • Group related items with labels and dividers
  • Use icon-left for actions, icon-right for metadata
  • Add aria-label on icon-only triggers
  • Use near the right viewport edge

Don't:

  • Don't use dropdowns for primary navigation — use tabs or links
  • Don't nest dropdowns inside dropdowns
  • Don't use dropdowns for form field selection — use <select> instead
  • Don't put more than 10 items in a single dropdown — break into sections or use a different pattern

CSS reference

This section documents how the component is built. For usage, see the sections above.

Tokens

Token Default What it controls
Menu background
Menu and divider border
Item hover background

Selectors

Selector Purpose
Positioning context (position: relative)
Clickable trigger — flex layout, hover styles
.dropdown-trigger:hover Trigger hover state
.dropdown-trigger .svg-icn Icon sizing inside trigger
.dropdown.is-open > .dropdown-trigger Active trigger state when menu is open
Rotating arrow indicator — transitions transform
.dropdown.is-open .dropdown-chevron Chevron rotated 180deg when open
Absolutely positioned menu panel — hidden by default
.dropdown-menu.is-right Right-aligned menu positioning
.dropdown.is-open .dropdown-menu Visible menu state
Clickable row — padding, hover background
.dropdown-item:hover Item hover — uses
.dropdown-item:focus-visible Item focus ring
.dropdown-item .svg-icn Icon sizing inside items
.dropdown-item.is-disabled Disabled item — reduced opacity, no pointer events
Destructive action — danger colour
.dropdown-item--danger:hover Danger item hover
Separator line between groups
Non-interactive section header
Supporting text below item label
Right-aligned trailing content inside an item
On this page
  • Trigger patterns
  • When to use a chevron
  • Menu alignment
  • Item patterns
  • Section labels
  • Disabled item
  • When to use what
  • JavaScript
  • Keyboard interactions
  • Accessibility
  • Structure reference
  • Usage rules
  • CSS reference
Previous

Accordion

Next

Dialog

Was this page helpful?

We use this feedback to improve our documentation.

Thanks for your feedback

Send feedback

© 2026 By Default