Cmpnts

Menu

Molecules

Menu

A list of actions in rows, usually opened from a Button in a Popover.


  • Code
    HTML
    <menu class="menu" aria-label="File options">
      <li><button type="button" class="button"><span>Rename</span></button></li>
      <li><button type="button" class="button"><span>Move to folder</span></button></li>
      <li><button type="button" class="button button--danger"><span>Delete file</span></button></li>
    </menu>

    Why it exists

    Applications have actions that don’t deserve a place on the page until someone asks for them: rename, move, delete. A Menu lists them in rows, with room for a heading or a shortcut.

    Its items are ordinary Buttons. The Menu makes them plain and full width and otherwise leaves them alone, so they keep their 48px targets, intent and focus ring, and there’s nothing new to learn.

    It is deliberately not an ARIA menu. role="menu" promises arrow keys, typeahead and focus management, which all need a script, and the library ships none. A promise it couldn’t keep would be worse for keyboard and screen-reader users than a list of Buttons that Tab moves through.

    When to use

    • For a list of actions or links, with headings and shortcuts if they help, in a Popover, Card or Sidebar.
    • Not for two or three Buttons in a row: that is a Button Group.
    • Not for choosing a value in a Form: that is a select or a Combobox.
    • Not for a site’s navigation hierarchy: that is a Navigation Tree.

    Rules

    • No ARIA Menu roles. A Menu is a list (<menu>), and Tab moves through it. role="menu" promises arrow keys, typeahead and focus management, which need a script the library doesn’t ship. So no role="menu", menuitem, role="none" or aria-haspopup="menu"; a Popover already provides Escape and light dismiss, and popovertarget exposes the expanded state.
    • Items are <li> holding a .button (or an <a class="button">). A destructive item is .button--danger, with a label that says what it does. A Link to the current page has aria-current="page" and shows as a tint, not a filled Button.
    • Checkable items are Buttons with aria-pressed and a check icon with .icon--on; the check keeps its space while off, so labels line up.

    Keyboard and screen readers

    The browser provides all of this. Script only what each item does.

    • Tab and Shift+Tab move between items, one at a time. Arrow keys do nothing here, as with any list of Buttons.
    • Enter and Space press a Button. Enter follows a Link.
    • Escape closes a Menu in a Popover, and returns focus to the Button that opened it.
    • A screen reader hears each item’s name and role, “pressed” from aria-pressed and “current page” from aria-current.
    • Choosing an item doesn’t close the Popover. Call hidePopover() from the script that does the work, or give the item popovertarget and popovertargetaction="hide".

    Actions in a Popover

  • Code
    HTML
    <button type="button" class="button" popovertarget="doc-menu">
      <span>Options</span>
      <svg class="icon" width="1em" height="1em" aria-hidden="true" focusable="false"><use href="#ChevronDown"/></svg>
    </button>
    
    <div id="doc-menu" popover class="popover">
      <menu class="menu" aria-label="Document options">
        <li class="menu__heading"><h3 class="micro-heading">Document</h3></li>
        <li>
          <button type="button" class="button">
            <svg class="icon" width="1em" height="1em" aria-hidden="true" focusable="false"><use href="#Duplicate"/></svg>
            <span>Duplicate</span>
            <kbd class="kbd">⌘D</kbd>
          </button>
        </li>
        <li>
          <button type="button" class="button">
            <svg class="icon" width="1em" height="1em" aria-hidden="true" focusable="false"><use href="#Download"/></svg>
            <span>Export JSON</span>
            <kbd class="kbd">⇧⌘E</kbd>
          </button>
        </li>
        <li role="separator" class="divider"></li>
        <li>
          <button type="button" class="button button--danger">
            <svg class="icon" width="1em" height="1em" aria-hidden="true" focusable="false"><use href="#Delete"/></svg>
            <span>Delete document</span>
          </button>
        </li>
      </menu>
    </div>

    A Popover makes its Menu strong through a flag, so it floats with a shadow and needs no modifier.

    Checkable Items

  • Code
    HTML
    <menu class="menu" aria-label="View">
      <li>
        <button type="button" class="button" aria-pressed="true">
          <svg class="icon icon--on" width="1em" height="1em" aria-hidden="true" focusable="false"><use href="#Check"/></svg>
          <span>Line numbers</span>
        </button>
      </li>
      <li>
        <button type="button" class="button" aria-pressed="false">
          <svg class="icon icon--on" width="1em" height="1em" aria-hidden="true" focusable="false"><use href="#Check"/></svg>
          <span>Word wrap</span>
        </button>
      </li>
    </menu>

    The check keeps its space while it’s off, so the labels don’t shift.

    Code
    HTML
    <nav aria-label="Account">
      <menu class="menu menu--plain">
        <li><a href="/profile" class="button" aria-current="page"><span>Profile</span></a></li>
        <li><a href="/billing" class="button"><span>Billing</span><span class="status status--warning status--plain"><span class="status__text">Due</span></span></a></li>
      </menu>
    </nav>

    --plain drops the Menu’s own surface where a Card or Sidebar already draws one.

    Do and Don’t

    DoDon’t
    Use <menu>, <li> and .button, and let Tab move through it.Add role="menu", menuitem or aria-haspopup="menu".
    Say what a destructive item does: “Delete document”.Label it “Delete” with colour as the only warning.
    Show a checkable item with aria-pressed and a .icon--on check.Add or remove the check icon, so labels shift.
    Set the type of a heading with a text atom on a heading element.Use <header> in a Menu.
    Let the container set the width.Give the Menu a width of its own.

    In Storybook

    See also

    • Popover: A layer anchored to the control that opens it, holding a Card or a Menu.
    • Button: An action on the page, such as saving a Form, opening a Dialog or changing a setting.
    • Button Group: A set of related Buttons laid out together, in a row or a column.
    • Divider: A rule between groups of content.

    Search the docs