Dropdown

Dropdown Figma Code Connected

Dropdown menus are hidden by default and can contain action lists with only a few items or more complicated filter or menu systems. Typically a button will show and hide them, though other components may also be used as a trigger.

Use them anywhere a set of links or controls do not need to be available on screen by default, when you need to show overflow controls, or when you have a complicated menu that does not rise to the level of a modal or drawer.

Basic dropdown

To create a dropdown, simply place both .hc-dropdown-toggle and .hc-dropdown-content elements inside of a parent .hc-dropdown.

The triggering element must currently be a <div> with class .hc-dropdown-toggle-button. You can turn this into a button by adding the same button classes as a regular button would get, but please note that the element itself has to be a <div>.


<div class="hc-dropdown">
  <div class="hc-dropdown-toggle">
    <div role="button" class="hc-button hc-button--primary hc-dropdown-toggle-button" tabindex="0">
      Dropdown toggle
    </div>
  </div>
  <menu class="hc-dropdown-content hc-dropdown-menu hc-dropdown-menu--context" tabindex="0">
    <a href="/" class="hc-dropdown-menu-item">
      <span class="hc-dropdown-menu-item-label">This is an item</span>
    </a>
    <a href="/" class="hc-dropdown-menu-item">
      <span class="hc-dropdown-menu-item-label">This is another item</span>
    </a>
    <a href="/" class="hc-dropdown-menu-item">
      <span class="hc-dropdown-menu-item-label">This is a third item</span>
    </a>
  </menu>
</div>

Important note

The dropdown toggle must unfortunately be a <div> due to an ongoing bug in Safari that prevents a <button> element from receiving focus.

This is still accessible and compliant, just give it role="button" as well as tabindex="0". Both of these are necessary for the dropdown functionality.

Future deprecation note

Now that the Popover API has full browser support, once anchor positioning also becomes widely available we will replace the current focus-within handling with the new native popover handling. Safari and Firefox remain to implement this, expected 2025.

JavaScript alternative handling

If you’d prefer to handle the dropdown show/hide yourself via JavaScript, append .hc-dropdown--js to the parent dropdown component and then manually add or remove the class .hc-dropdown--is-visible to this element.

Honeycomb handles the display and animation, but you will be responsible for any click handlers to add or remove this display class.


<div class="hc-dropdown hc-dropdown--js" id="ddjs">
  <div class="hc-dropdown-toggle">
    <div role="button" class="hc-button hc-button--primary" tabindex="0" onclick="document.getElementById('ddjs').classList.toggle('hc-dropdown--is-visible')">
      Dropdown toggle
    </div>
  </div>
  <div class="hc-dropdown-content" tabindex="0">
    <menu class="flex flex-col px-3 py-3 whitespace-nowrap">
      <a href="/" class="px-2 py-1 rounded hover:bg-gray-100">This is an item</a>
      <a href="/" class="px-2 py-1 rounded hover:bg-gray-100">This is another item</a>
      <a href="/" class="px-2 py-1 rounded hover:bg-gray-100">This is a third item</a>
    </menu>
  </div>
</div>

Interactions and states

Dropdowns have a subtle default fade-in and slide-up animation on reveal, with the reverse on hide. They have a default drop shadow as well. All of this is handled natively.

No javascript is required! As of v0.2.5 all dropdown interactions are now handled by CSS only. The parent .hc-dropdown element uses the :focus-within pseudo-class: when the triggering button gets focus, visibility and opacity styles are applied to the .hc-dropdown-content. Because it uses :focus-within, user actions inside of the dropdown itself do not cause it to close.

It’s important that the .hc-dropdown-toggle-button element is inside of an .hc-dropdown-toggle element. The later is used to maintain cursor: pointer; on the button when the dropdown is open.

The dropdown will close when the user clicks outside of it.

Dropdown button with caret

There is a special button variation specifically for dropdowns! This variation is used in the header for both the primary dropdown menus as well as the account menu dropdown.

Apply .hc-button--dropdown to get the basic effect. There are specific child elements and classes for content and the caret as well; content inside should have .hc-button--dropdown--content and the caret must be a <sub> element with class .hc-button--dropdown--caret.


<div class="hc-dropdown">
  <div class="hc-dropdown-toggle">
    <div role="button" class="hc-button hc-button--primary hc-dropdown-toggle-button" tabindex="0">
      Manage account
      <sub class="hc-button--dropdown--caret">toggle</sub>
    </div>
  </div>
  <menu class="hc-dropdown-content">
    <div class="hc-dropdown-list hc-dropdown-section--divider">
      <a href="/" class="hc-dropdown-list-link">
        <i class="hc-icon hc-icon--lock hc-icon--20"></i>
        Change password
      </a>
      <a href="/" class="hc-dropdown-list-link">
        <i class="hc-icon hc-icon--settings hc-icon--20"></i>
        Preferences
      </a>
      <a href="/" class="hc-dropdown-list-link">
        <i class="hc-icon hc-icon--language hc-icon--20"></i>
        Preferred language
      </a>
    </div>
  </menu>
</div>

Toggle direction

Dropdowns open centered to the toggle button by default. You can control this direction with utility classes; currently right-justified and left-justified are supported.

Left aligned toggle
This should be fixed to the left of the button.
Right aligned toggle
This should be fixed to the right of the button.

<div class="hc-dropdown">
  <div class="hc-dropdown-toggle">
    <div role="button" class="hc-button hc-button--primary hc-dropdown-toggle-button" tabindex="0">
      Left aligned
      <sub class="hc-button--dropdown--caret">toggle</sub>
    </div>
  </div>
  <menu class="hc-dropdown-content hc-dropdown-content--left w-48 p-4">
    This should be fixed to the left of the button.
  </menu>
</div>
<div class="hc-dropdown">
  <div class="hc-dropdown-toggle">
    <div role="button" class="hc-button hc-button--primary hc-dropdown-toggle-button" tabindex="0">
      Right aligned
      <sub class="hc-button--dropdown--caret">toggle</sub>
    </div>
  </div>
  <menu class="hc-dropdown-content hc-dropdown-content--right w-48 p-4">
    This should be fixed to the right of the button.
  </menu>
</div>

Honeycomb has a few common preset dropdown menu systems available. Included are a standard context menu, the user menu triggered from the Header, and a stacked layout that can contain top, scrollable middle, and bottom content sections.

In general, create the dropdown with the same set of dropdown classes as documented above. If you have only one menu, this can be the same .hc-dropdown-content element.

If you have a more complicated menu or more than one menu, wrap them all inside of a <div> that is instead the .hc-dropdown-content wrapper element. Each menu inside the dropdown should then use a <menu> element with various classes for the different menu systems documented below.

Context menus offer a small set of actions or links inside of a dropdown menu. Add the class .hc-dropdown-menu and the modifier .hc-dropdown-menu--context to the <menu> element. Place menu items inside this element.

To include fixed space for an icon within each menu item, even when you don’t provide an icon for alignment purposes, add the modifer .hc-dropdown-menu--with-icons. Likewise, add .hc-dropdown-menu--with-indicators for the right side indicator space.

If you’d like to include an indicator or count indicator, make that the final element inside of the link.


<div class="hc-dropdown-content hc-is--visible">
  <menu class="hc-dropdown-menu hc-dropdown-menu--context hc-dropdown-menu--with-icons hc-dropdown-menu--with-indicators">
    <a href="/" class="hc-dropdown-menu-item">
      <i class="hc-icon hc-icon--next-steps"></i>
      <span class="hc-dropdown-menu-item-label">Create a next step</span>
    </a>
    <a href="/" class="hc-dropdown-menu-item">
      <i class="hc-icon hc-icon--check-circle"></i>
      <span class="hc-dropdown-menu-item-label">Mark as achieved</span>
    </a>
    <a href="/" class="hc-dropdown-menu-item">
      <span class="hc-dropdown-menu-item-label">Resolve warnings</span>
      <span class="hc-indicator-count">2</span>
    </a>
    <a href="/" class="hc-dropdown-menu-item">
      <i class="hc-icon hc-icon--archive"></i>
      <span class="hc-dropdown-menu-item-label">Archive this activity item</span>
    </a>
  </menu>
</div>

The user account dropdown menu opened from the Header also exists as a preconfigured component here. Append the classes .hc-dropdown-menu .hc-dropdown-menu--account to the first <menu> element. Avatar is an optional include if your app uses user avatars.

Menu items below the upper account info section use a pair of context menus, documented above.


<div class="hc-dropdown-content hc-is--visible">
  <menu class="hc-dropdown-menu hc-dropdown-menu--account">
    <span class="hc-avatar hc-avatar--blue hc-avatar--header">AG</span>
    <span class="hc-dropdown-menu--account-names">
      <span class="hc-is--primary">Falco Lombardi</span>
      <span class="hc-is--secondary">flombar02</span>
    </span>
    <button class="hc-button hc-button--secondary hc-button--icon hc-button--lg" aria-label="User account settings">
      <i class="hc-icon hc-icon--settings"></i>
    </button>
  </menu>
  <menu class="hc-dropdown-menu hc-dropdown-menu--context hc-dropdown-menu--with-indicators">
    <a href="/" class="hc-dropdown-menu-item">
      <i class="hc-icon hc-icon--bell"></i>
      <span class="hc-dropdown-menu-item-label">Notifications</span>
      <span class="hc-indicator-count hc-indicator--danger">2</span>
    </a>
    <a href="/" class="hc-dropdown-menu-item">
      <i class="hc-icon hc-icon--adjustment"></i>
      <span class="hc-dropdown-menu-item-label">Preferences</span>
    </a>
    <a href="/" class="hc-dropdown-menu-item">
      <i class="hc-icon hc-icon--support"></i>
      <span class="hc-dropdown-menu-item-label">Open a support ticket</span>
    </a>
  </menu>
  <menu class="hc-dropdown-menu hc-dropdown-menu--context hc-dropdown-menu--logout">
    <a href="/" class="hc-dropdown-menu-item">
      <i class="hc-icon hc-icon--log-out"></i>
      <span class="hc-dropdown-menu-item-label">Logout</span>
    </a>
  </menu>
</div>

A stacked dropdown menu has preconfigured title, content, and footer sections. The content section has a max height of 320rem (or 33% of the viewport height, whichever is less), and will scroll on overflow. The title and footer sections are fixed and always present if included.

This is usful for a combobox where you’d like a text input stuck to the top that filters a selectable list, with a fixed position CTA button at the bottom.


<menu class="hc-dropdown-content hc-is--visible hc-dropdown-menu hc-dropdown-menu--stacked">
  <header class="hc-dropdown-menu-header">
    <input type="text" class="hc-input" placeholder="Filter groups...">
  </header>
  <div class="hc-dropdown-menu-content">
    <label class="hc-form-control hc-dropdown-menu-item">
      <input type="checkbox" class="hc-checkbox" />
      <span class="hc-label">
          <span class="hc-label-text">Fairview Elementary</span>
      </span>
    </label>
    <label class="hc-form-control hc-dropdown-menu-item">
      <input type="checkbox" class="hc-checkbox" />
      <span class="hc-label">
          <span class="hc-label-text">St. Charles Borromeo</span>
      </span>
    </label>
    <label class="hc-form-control hc-dropdown-menu-item">
      <input type="checkbox" class="hc-checkbox" />
      <span class="hc-label">
          <span class="hc-label-text">Discovery School</span>
      </span>
    </label>
    <label class="hc-form-control hc-dropdown-menu-item">
      <input type="checkbox" class="hc-checkbox" />
      <span class="hc-label">
          <span class="hc-label-text">Fox Hill Preschool</span>
      </span>
    </label>
    <label class="hc-form-control hc-dropdown-menu-item">
      <input type="checkbox" class="hc-checkbox" />
      <span class="hc-label">
          <span class="hc-label-text">St. Maximillian Kolbe</span>
      </span>
    </label>
    <label class="hc-form-control hc-dropdown-menu-item">
      <input type="checkbox" class="hc-checkbox" />
      <span class="hc-label">
          <span class="hc-label-text">Ss. Coleman-Neumann</span>
      </span>
    </label>
    <label class="hc-form-control hc-dropdown-menu-item">
      <input type="checkbox" class="hc-checkbox" />
      <span class="hc-label">
          <span class="hc-label-text">Monisgnor Bonner HS</span>
      </span>
    </label>
    <label class="hc-form-control hc-dropdown-menu-item">
      <input type="checkbox" class="hc-checkbox" />
      <span class="hc-label">
          <span class="hc-label-text">O'Hara Elementary</span>
      </span>
    </label>
    <label class="hc-form-control hc-dropdown-menu-item">
      <input type="checkbox" class="hc-checkbox" />
      <span class="hc-label">
          <span class="hc-label-text">Ss. Peter and Paul</span>
      </span>
    </label>
    <label class="hc-form-control hc-dropdown-menu-item">
      <input type="checkbox" class="hc-checkbox" />
      <span class="hc-label">
          <span class="hc-label-text">Ss. Simon and Jude</span>
      </span>
    </label>
    <label class="hc-form-control hc-dropdown-menu-item">
      <input type="checkbox" class="hc-checkbox" />
      <span class="hc-label">
          <span class="hc-label-text">St. Andrews</span>
      </span>
    </label>
    <label class="hc-form-control hc-dropdown-menu-item">
      <input type="checkbox" class="hc-checkbox" />
      <span class="hc-label">
          <span class="hc-label-text">Wayne Elementary School</span>
      </span>
    </label>
  </div>
  <footer class="hc-dropdown-menu-footer">
    <button class="hc-button hc-button--primary hc-button--success hc-button--full">
      <i class="hc-icon hc-icon--filter"></i>
      Apply group filters
    </button>
  </footer>
</menu>