Honeycomb

Dropdown

The dropdown shows a list of possible actions.

The dropdown is used to show a list of options, such as links in a sub-menu or options in a data table, for example. It uses a balloon to display a navigation element and has to be attached to a target since it's position is relative to it.

The target is the element that, when interacted with, toggles the appearance of the dropdown.

We strongly advise that you use the Dropdown plugin since it makes things a lot easier by handling all the necessary attributes to toggle dropdowns and also set up all the required accessibility features, so you won't have to worry about keeping them in sync.

Building the Dropdown

The dropdown component requires a specific HTML structure in order to work correctly.

  • Wrap the target element and the list of items with a flix-dropdown container;
  • Ideally the target should be a button;
  • If the button doesn't have any text content (just an icon), add a meaningful aria-label to the button;
  • Add a unique id to flix-dropdown__items-container element;
  • Add the hidden attribute as well, if you wish to initialize the dropdown hidden by default;
  • If you want it to be active make sure the hidden attribute is removed from flix-dropdown__items-container and flix-dropdown--active CSS class is present on the flix-dropdown element;
  • Finally, connect the dropdown target to the list by passing the list id as value to the target's data-dropdown attribute;
  • If you wish to change the default event trigger to hover, just add data-event="hover" to the target;

To add a divider item, simply insert a <hr class="flix-divider"> in one of the list items, do not put it inside the "link" wrapper.

Voila! The plugin will automatically add the aria roles and attributes and will setup all te event handlers for you.

<div class="flix-dropdown">
  <button type="button" class="flix-btn flix-btn--primary" data-dropdown="dropdown-menu">
    Open dropdown
    <flix-icon class="flix-btn__icon" name="arrow-down"></flix-icon>
  </button>
  <div id="dropdown-menu" hidden class="flix-dropdown__items-container">
    <ul class="flix-dropdown__items">
      <li class="flix-dropdown__item">
        <a class="flix-dropdown__link" aria-current="true" href="#">
          <flix-icon name="edit" solid="true"></flix-icon>
          Edit
        </a>
      </li>
      <li class="flix-dropdown__item">
        <a class="flix-dropdown__link" href="#">
          <flix-icon name="share"></flix-icon>
          Share
        </a>
      </li>
      <li class="flix-dropdown__item">
        <hr class="flix-divider" />
      </li>
      <li class="flix-dropdown__item">
        <span class="flix-dropdown__link">
          More options:
        </span>
      </li>
      <li class="flix-dropdown__item">
        <button class="flix-dropdown__link" type="button">
          <flix-icon name="delete"></flix-icon>
          Delete
        </button>
      </li>
    </ul>
  </div>
</div>

Modifiers

By default, the dropdown positions itself in the center of the target element. Some modifiers are available to control the position of the dropdown:

flix-dropdown--top
positions the dropdown on top of the target
flix-dropdown--left
aligns the dropdown to the left of the target
flix-dropdown--right
aligns the dropdown to the right of the target

Idea initiative

<div class="flix-box">
  <div class="flix-grid">
    <div class="flix-col">
      <h3 class="flix-h3">Idea initiative</h3>
    </div>
    <div class="flix-col">
      <section class="flix-has-text-right">
        <div class="flix-dropdown flix-dropdown--top flix-dropdown--left">
          <button
            type="button"
            aria-label="Options"
            class="flix-btn flix-btn--square flix-btn--link"
            data-dropdown="dropdown-idea-example"
          >
            <i class="flix-btn__icon flix-icon flix-icon--size-4 flix-icon-kebab" aria-hidden="true"></i>
          </button>
          <div id="dropdown-idea-example" hidden class="flix-dropdown__items-container">
            <ul class="flix-dropdown__items">
              <li class="flix-dropdown__item">
                <a class="flix-dropdown__link" href="#">Edit</a>
              </li>
              <li class="flix-dropdown__item">
                <a class="flix-dropdown__link" href="#">Share</a>
              </li>
              <li class="flix-dropdown__item">
                <a class="flix-dropdown__link" href="#">Delete</a>
              </li>
            </ul>
          </div>
        </div>
      </section>
    </div>
  </div>
</div>

Scrollable content

When there are too many items inside of dropdown it limits its height and shows visual scroll indicators on both sides. Those indicators indicate to the user that the content can be scrolled.

Default height limit is 315px and displays 7 items in full. If needed you can adjust this limit with the max-height CSS property on the flix-dropdown__items element.

<div class="flix-dropdown">
  <button type="button" class="flix-btn flix-btn--primary" data-dropdown="dropdown-menu-scrollable">
    Open scrollable dropdown
    <flix-icon class="flix-btn__icon" name="arrow-down"></flix-icon>
  </button>
  <div id="dropdown-menu-scrollable" hidden class="flix-dropdown__items-container">
    <ul class="flix-dropdown__items">
      <li class="flix-dropdown__item">
        <a class="flix-dropdown__link" href="#">
          <flix-icon name="offer"></flix-icon>
          Add
        </a>
      </li>
      <li class="flix-dropdown__item">
        <a class="flix-dropdown__link" aria-current="true" href="#">
          <flix-icon name="edit" solid="true"></flix-icon>
          Edit
        </a>
      </li>
      <li class="flix-dropdown__item">
        <a class="flix-dropdown__link" href="#">
          <flix-icon name="copy"></flix-icon>
          Copy
        </a>
      </li>
      <li class="flix-dropdown__item">
        <a class="flix-dropdown__link" href="#">
          <flix-icon name="share"></flix-icon>
          Share
        </a>
      </li>
      <li class="flix-dropdown__item">
        <hr class="flix-divider" />
      </li>
      <li class="flix-dropdown__item">
        <span class="flix-dropdown__link">
          More options:
        </span>
      </li>
      <li class="flix-dropdown__item">
        <button class="flix-dropdown__link" type="button">
          <flix-icon name="delete"></flix-icon>
          Delete
        </button>
      </li>
      <li class="flix-dropdown__item">
        <button class="flix-dropdown__link" type="button">
          <flix-icon name="archive"></flix-icon>
          Archive
        </button>
      </li>
      </li>
      <li class="flix-dropdown__item">
        <button class="flix-dropdown__link" type="button">
          <flix-icon name="reset"></flix-icon>
          Reset
        </button>
      </li>
    </ul>
  </div>
</div>

Making it work without the plugin

Before you continue we would really like to emphasize that you should use the plugin!

There are several steps you need to pay attention to make an accessible dropdown component:

  • Wrap the target element and the list of items with a flix-dropdown container;
  • Add the flix-dropdown__items-container div and put the list of items (flix-dropdown__items) inside:
    • Add an id (list_id) to the flix-dropdown__items to connect it to the target via aria-controls attribute;
    • Add the hidden attribute to the list to hide it from assistive technologies;
  • Add a button to be the target of the dropdown:
    • Connect the target to the flix-dropdown__items list by using aria-controls="{list_id}>";
    • Add aria-haspopup="menu" to the target to inform assistive technologies that this is a dropdown component;
    • Add aria-expanded="true" or "false" attribute to inform assistive technologies of the status of the target;
    • If the button doesn't have any text content, add a meaningful aria-label for accessibility;
  • The dropdown should also implement the menu and menuitem roles:
    • Add role="menu" to the list element (the list that has the menu items);
    • Add role="presentation on the list items, since they no longer represent a simple list but are part of a sub menu context;
    • Add role="menuitem" to the link elements;

When the user interacts with the target you must toggle and keep in sync:

  • flix-dropdown--active modifier class;
  • The aria-expanded to be "true" or "false" on the target accordingly;
  • The hidden attribute on flix-dropdown__items-container.

You must also allow closing the dropdown by pressing ESC on the keyboard.

Check the related guides section for relevant documentation you can use as reference to implement an accessible dropdown menu.