The page navigation is complete. You may now navigate the page content as you wish.
Skip to main content

Dropdown

Updated in v4.15.0

Displays a list of actions or options revealed by a toggle button. Identifiable by the chevron icon in the button.

A dropdown is a flexible component that displays a list of actions or options to the user. It should not be confused with Select, which is used in forms as a way for the user to make a selection from a list.

Take care to use dropdowns correctly. A crowded or overly complex dropdown can lead to a frustrating user experience, especially for assistive technology users. Contact the Design Systems Team to discuss alternative options if a dropdown feels too complex.

Usage

When to use

  • To display a list of actions or links under a single button toggle.
  • To allow singular or multiple selection outside of a form, such as within filtering.
  • To provide the user with a way to easily switch context within the application.

When not to use

  • In forms when providing the user with options to choose from, consider Select.

Toggle

Types

Toggles come in two variant types: button and icon.

Size

ToggleButtons come in two sizes: small and medium. This allows for placement in ButtonSets with buttons of the same size.

ToggleIcons come in two sizes: small and medium.

While we provide a small size variant, we recommend only using this for the Overflow menu within Tables because the icons and images start to become unrecognizable in smaller sizes.

Chevron usage

Open Toggles use icon chevron-up, while closed Toggles use chevron-down.

ToggleButtons require a visible chevron to indicate interactivity and provide distinction between Dropdowns and standard Buttons.

Example of open and closed dropdowns

We strongly recommend providing visible chevrons on most instances of ToggleIcons to indicate interactivity. That said, it’s common to see ToggleIcons that use the more-horizontal icon without chevrons. Their placement, usually in the last column of a Table, is typically indicative of this type of interaction.

Example of open and closed dropdowns

List

Placement

Lists can be positioned to the left or right of the Toggle, and above or below the Toggle to fit more appropriately within the UI. Lists do not currently have collision detection.

Dropdown list placement examples

Size

Width

By default, Lists have a minimum width of 200px and a maximum width of 400px. This means if there’s a long string in a ListItem, the List will automatically expand up to 400px to accommodate the content before it wraps.

  • Signed in as
  • name@email.com

If you do not want the width of the List to expand automatically to accommodate the widest ListItem, you can indicate a specific width between 200px–400px.

  • Consul version v1.10.6
  • Import to Terraform
  • Copy and run this command in Terraform to import and manage this resource via our Terraform Provider
  • Docs: Import usage

Height

The height of the ListContainer is automatically determined based on the contents, but the height can also be set manually. We recommend setting the height manually if you know the list will be long. In code, the @height property actually acts as a max-height.

A Header provides a fixed space at the top of the List. Typically, Headers house a search feature that allows the user to search/filter through the available options in the list. This is great for really long lists when filtering on complex datasets.

A Footer provides a fixed space at the bottom of the List. Typically, Footers house actions related to the ListItems, e.g., when found in a filtering pattern an "Apply" Button can be used to submit the selections.

ListItem

Types

For maximum flexibility, we offer a variety of ListItems options.

Interactive ListItems

Use Interactive ListItems for actions (buttons) or links.

  • Use Interactive - Critical for destructive actions.
  • Use Interactive - Action for everything else.

Interactive ListItem types

Selection ListItems

Selection ListItems allow the user to select one or more options within a Dropdown.

  • Use Checkmark for switching context, e.g., organization switchers, project switchers, etc. Use for single selection only, as it doesn't provide enough indication that multi-selection is possible. For multi-selection, use Checkbox.
  • Use Checkbox for multi-selection within a form or larger filter pattern.
  • Use Radio for single selection within a form or larger filter pattern.

Selection ListItem types

Do

Use Checkmark for context switching.

Example of proper checkmark list items

Don’t

Don't use Checkmark instead of Radio in larger filter patterns.

Example of incorrect checkmark list items

Non-interactive

Non-interactive ListItems help provide structure and context to a Dropdown. Types include: Description, Loading, Separator, and Title.

Non-interactive ListItem types

Do

Users may not understand why something is taking additional time to load. If possible, determine what should be displayed prior to the user opening the dropdown (e.g., on page load). If that is not possible, provide an informative loading message.

Example of loading list item

Generic

The Generic ListItem allows you to add generic content in place of a ListItem. It includes predefined left and right padding to ensure proper alignment with other ListItems in the List.

Be careful not to misuse or overuse the Generic ListItem. Relying on this escape hatch too often could result in an overly complex Dropdown.

Generic ListItem type

Icon usage

Icons in ListItems are optional. Generally, we recommend letting the text speak for itself, but icons can add value in the following situations:

  • When they reinforce the content, e.g., edit for an edit or rename action.
  • When using Interactive ListItems, a trailingIcon can indicate that a link is external.
  • When using Critical ListItems; read more about how color blind users see critical actions in our UIs.
  • To avoid inconsistent icon use within the same List. Instead use icons in all ListItems. Doing so keeps the text aligned so the eye can scan the list of options more easily.
Do

Use icons consistently and when they reinforce the content.

Don’t

Avoid inconsistent icon use.

Badge usage

Badges in Interactive ListItems are optional. We recommend using only the small Badge option to align more closely with the text line height. Badges should be used sparingly and only when their use adds contextual value. Examples of appropriate use of Badge inside an Interactive ListItem include:

  • When an item is in beta or behind a feature flag, i.e., a new item that users should be able to locate easily.
  • When an item has vital information that users should be able to see at a glance, i.e., a unique status.
  • When an item should be distinguished from others in the list, e.g., an item view is Public vs Private.

Dropdown use case examples

The Figma component will not fully reflect the Badge wrapping behavior expected in the Ember component due to current known limitations in Figma’s auto layout settings.

Refer to the Badge guidelines to help inform choices around color and icon use.

Content

While there are no character limits for ListItems, we recommend keeping them short and concise so the List is easy to scan.

Critical action patterns

We recommend adding a second confirmation layer after the user clicks “Delete” (e.g., showing a confirmation Modal that requires the user to take another action before proceeding). This safeguards against accidental clicks by requiring users to confirm the destructive action.

Do

example of how to use a second confirmation layer

Don’t

example of how not to use a second confirmation layer

How to use this component

The component uses the Popover API to display the dropdown list. A third-party library called Floating UI provides anchoring and positioning functionality.

To make the invocation more flexible and intuitive, we provide contextual components for Toggles, ListItems, Header and Footer. For example, <Hds::Dropdown::ListItem::Separator /> would be contextually expressed as <D.Separator />.

<Hds::Dropdown as |D|>
  <D.ToggleButton @text="Menu" />
  <D.Title @text="Title Text" />
  <D.Description @text="Descriptive text goes here." />
  <D.Interactive @href="#">Add</D.Interactive>
  <D.Interactive @href="#">Add More</D.Interactive>
  <D.Interactive @href="#">Add Another Thing Too</D.Interactive>
  <D.Separator />
  <D.Interactive @route="components" @icon="trash" @color="critical">Delete</D.Interactive>
</Hds::Dropdown>

ToggleButton

The basic invocation of ToggleButton requires @text to be passed. By default, it renders a primary button with a chevron icon.

<Hds::Dropdown as |D|>
  <D.ToggleButton @text="Text Toggle" />
  <D.Interactive @route="components">Item One</D.Interactive>
  <D.Interactive @route="components">Item Two</D.Interactive>
  <D.Interactive @route="components">Item Three</D.Interactive>
  <D.Interactive {{on "click" D.close}}>Item Four (closes on click)</D.Interactive>
  <D.Separator />
  <D.Interactive @route="components" @color="critical" @icon="trash">Delete</D.Interactive>
</Hds::Dropdown>

Alternatively, pass secondary to @color to display a secondary button with a chevron icon.

<Hds::Dropdown as |D|>
  <D.ToggleButton @text="Text Toggle" @color="secondary" />
  <D.Interactive @route="components">Item One</D.Interactive>
  <D.Interactive @route="components">Item Two</D.Interactive>
  <D.Interactive @route="components">Item Three</D.Interactive>
  <D.Interactive {{on "click" D.close}}>Item Four (closes on click)</D.Interactive>
  <D.Separator />
  <D.Interactive @route="components" @color="critical" @icon="trash">Delete</D.Interactive>
</Hds::Dropdown>

ToggleIcon

ToggleIcon as overflow menu

Overflow menus are often found in the last column of a Tables. This is the only use case where it is acceptable to use @hasChevron=false. @text is still required, because it supplies the aria-label for ToggleIcon.

<Hds::Dropdown as |D|>
  <D.ToggleIcon @icon="more-horizontal" @text="Overflow Options" @hasChevron={{false}} />
  <D.Interactive @route="components">Create</D.Interactive>
  <D.Interactive @route="components">Read</D.Interactive>
  <D.Interactive @route="components">Update</D.Interactive>
  <D.Separator />
  <D.Interactive @route="components" @icon="trash" @color="critical">Delete</D.Interactive>
</Hds::Dropdown>

ToggleIcon as user menu

@text is still required, because it supplies the aria-label for ToggleIcon.

<Hds::Dropdown as |D|>
  <D.ToggleIcon @icon="user" @text="user menu" />
  <D.Title @text="Signed In" />
  <D.Description @text="email@domain.com" />
  <D.Separator />
  <D.Interactive @route="components">Settings and Preferences</D.Interactive>
  <D.Interactive @route="components" @icon="trash" @color="critical">Delete</D.Interactive>
</Hds::Dropdown>

ToggleIcon with other icons

Pass any icon name to @icon to change the icon used in ToggleIcon. @text is still required, because it supplies the aria-label for ToggleIcon.

<Hds::Dropdown as |D|>
  <D.ToggleIcon @icon="settings" @text="settings menu" />
  <D.Title @text="Signed In" />
  <D.Description @text="email@domain.com" />
  <D.Separator />
  <D.Interactive @route="components">Settings and Preferences</D.Interactive>
  <D.Interactive @route="components" @icon="trash" @color="critical">Delete</D.Interactive>
</Hds::Dropdown>

List placement

By default, the list is positioned below the button, aligned to the right. To change the list position pass bottom-left, top-left, or top-right to @listPosition on the Dropdown component.

<Hds::Dropdown @listPosition="bottom-left" as |D|>
  <D.ToggleButton @text="Text Toggle" />
  <D.Interactive @route="components">Item One</D.Interactive>
  <D.Interactive @route="components">Item Two</D.Interactive>
  <D.Interactive @route="components">Item Three</D.Interactive>
  <D.Interactive {{on "click" D.close}}>Item Four (closes on click)</D.Interactive>
  <D.Separator />
  <D.Interactive @route="components" @icon="trash" @color="critical">Delete</D.Interactive>
</Hds::Dropdown>

In contexts where the Dropdown needs to be inline, to inherit the alignment from a parent, you can use the @isInline argument (and set the @listPosition accordingly to your needs):

<div class="doc-dropdown-mock-text-align-right">
  <Hds::Dropdown @isInline={{true}} @listPosition="bottom-right" as |D|>
    <D.ToggleButton @text="Text Toggle" @color="secondary" />
    <D.Interactive @route="components">Item One</D.Interactive>
    <D.Interactive @route="components">Item Two</D.Interactive>
    <D.Interactive @route="components">Item Three</D.Interactive>
  </Hds::Dropdown>
</div>

Collision detection

Setting the @enableCollisionDetection argument to true will automatically adapt the list position relative to the viewport to avoid collisions with the browser window boundaries. This means that when an end-user scrolls the page, or resizes the browser, the position of the list on the page dynamically adapts to these changes.

<Hds::Dropdown @enableCollisionDetection={{true}} as |D|>
  <D.ToggleButton @text="Text Toggle" />
  <D.Interactive @route="components">Item One</D.Interactive>
  <D.Interactive @route="components">Item Two</D.Interactive>
  <D.Interactive @route="components">Item Three</D.Interactive>
  <D.Interactive {{on "click" D.close}}>Item Four (closes on click)</D.Interactive>
  <D.Separator />
  <D.Interactive @route="components" @icon="trash" @color="critical">Delete</D.Interactive>
</Hds::Dropdown>

List size

You can explicitly control the height or width of a list. Any acceptable value (px, rem, em) can be declared.

The @height argument actually sets a max-height which prevents the list from growing past a certain height.

<Hds::Dropdown @height="170px" @width="250px" as |D|>
  <D.ToggleButton @text="Text Toggle" />
  <D.Interactive @route="components">Item One</D.Interactive>
  <D.Interactive @route="components">Item Two</D.Interactive>
  <D.Interactive @route="components">Item Three</D.Interactive>
  <D.Interactive @route="components">Item Four</D.Interactive>
  <D.Interactive @route="components">Item Five</D.Interactive>
  <D.Interactive @route="components">Item Six</D.Interactive>
  <D.Interactive @route="components">Item Seven</D.Interactive>
</Hds::Dropdown>

You can also set the width of a list to match the toggle button.

<Hds::Dropdown @matchToggleWidth={{true}} as |D|>
  <D.ToggleButton @text="Text Toggle" />
  <D.Interactive @route="components">Item One</D.Interactive>
  <D.Interactive @route="components">Item Two</D.Interactive>
  <D.Interactive @route="components">Item Three</D.Interactive>
  <D.Interactive @route="components">Item Four</D.Interactive>
</Hds::Dropdown>

When @matchToggleWidth is set, the @width value (if set) is overridden.

It is possible that you may want to add a list footer for things like a set of buttons for a filter control:

<Hds::Dropdown @height="284px" as |D|>
  <D.ToggleButton @icon="tag" @text="Tags" @color="secondary" />
  <D.Checkbox>access</D.Checkbox>
  <D.Checkbox>homework</D.Checkbox>
  <D.Checkbox>discovery</D.Checkbox>
  <D.Checkbox>memories</D.Checkbox>
  <D.Checkbox>music</D.Checkbox>
  <D.Checkbox>pharell</D.Checkbox>
  <D.Checkbox>punk</D.Checkbox>
  <D.Checkbox>random</D.Checkbox>
  <D.Checkbox>robots</D.Checkbox>
  <D.Checkbox>tag</D.Checkbox>
  <D.Footer @hasDivider={{true}}>
    <Hds::ButtonSet>
      <Hds::Button @text="Apply filters" @isFullWidth={{true}} @size="small" />
      <Hds::Button @text="Cancel" @color="secondary" @size="small" />
    </Hds::ButtonSet>
  </D.Footer>
</Hds::Dropdown>

Content rendering in DOM

By default, the content of the Dropdown is not rendered into the browser when the Dropdown is closed.

To change this behavior, you can use the @preserveContentInDom argument so that the content is rendered in the DOM, regardless of whether the Dropdown is open or closed.

<Hds::Dropdown @preserveContentInDom={{true}} as |D|>
  <D.ToggleButton @text="Text Toggle" />
  <D.Interactive @route="components">This item should always be present in the DOM, regardless of whether the dropdown is open or closed</D.Interactive>
</Hds::Dropdown>

ListItem::Interactive

ListItem::Interactive renders the correct element based on the passing of a @route, @href, or the addition of a click event (e.g., {{on "click" this.myAction}}). Internally, the component uses the Hds::Interactive utility component.

Rendering a button

If you add an event handler (no @href or @route), a <button> element will be rendered:

<ul class="hds-dropdown__list">
  <Hds::Dropdown::ListItem::Interactive {{on "click" this.myAction}}>
    Run command
  </Hds::Dropdown::ListItem::Interactive>
</ul>

You can pass an @icon argument to add a leading icon:

<ul class="hds-dropdown__list">
  <Hds::Dropdown::ListItem::Interactive {{on "click" this.myAction}} @icon="build">
    Run command
  </Hds::Dropdown::ListItem::Interactive>
</ul>

Internal Link?

When using the @href argument, you’re indicating an external link (instead of a route). So, a few relevant HTML attributes are added—target="_blank" and rel="noopener noreferrer". However, if the @href really does point to an internal link or uses a different protocol (e.g., mailto or ftp), pass @isHrefExternal=false to the component and it will not add any extra HTML attributes.

If you pass an @href argument, a link (<a> element) will be generated:

<ul class="hds-dropdown__list">
  <Hds::Dropdown::ListItem::Interactive @href="https://www.hashicorp.com/request-demo/terraform">
    Request a demo
  </Hds::Dropdown::ListItem::Interactive>
</ul>

To indicate that the link points to an external resource, you can use @trailingIcon and assign it an icon name like external-link, docs-link, guide-link, or learn-link.

<ul class="hds-dropdown__list">
  <Hds::Dropdown::ListItem::Interactive @href="https://www.hashicorp.com/request-demo/terraform" @trailingIcon="external-link">
    Request a demo
  </Hds::Dropdown::ListItem::Interactive>
</ul>

Rendering a LinkTo (with @route)

Pass a @route to render Ember <LinkTo>. If the route is external to your current engine, pass @isRouteExternal=true to use <LinkToExternal> instead of <LinkTo>. For more details see the Hds::Interactive component documentation. All the standard arguments for the <LinkTo/LinkToExternal> components are supported (e.g., models/model/query/current-when/replace).

<ul class="hds-dropdown__list">
  <Hds::Dropdown::ListItem::Interactive @route="my.page.route" @model="my.page.model">
    Activate cluster
  </Hds::Dropdown::ListItem::Interactive>
</ul>

With a loading “interactive” item

There may be use cases when it’s necessary to put an item in a “loading” state while the app performs some operations (e.g., asynchronously checking the user’s permissions to execute a certain operation once the Toggle’s been clicked).

Pass the argument @isLoading=true to the item. This will show a “loading” icon (even if an argument @icon is provided) and sets the item as non-interactive until the value of @isLoading is set to false again.

<Hds::Dropdown as |D|>
  <D.ToggleIcon @icon="more-horizontal" @text="Overflow Options" @hasChevron={{false}} />
  <D.Interactive @route="components" @isLoading={{true}} @color="action" @icon="edit">Edit cluster</D.Interactive>
  <D.Interactive @route="components" @icon="trash" @color="critical">Delete</D.Interactive>
</Hds::Dropdown>

ListItem::CopyItem

To enable users to copy a snippet of code (eg. URLs, secrets, code blocks, etc.) use ListItem::CopyItem.

Using the @isTruncated argument it is possible to constrain the text to one-line and truncate it if it does not fit the available space. Please be aware there are serious accessibility concerns with using this feature.

<Hds::Dropdown as |D|>
  <D.ToggleButton @listPosition="bottom-left" @text="Create run task" @color="secondary" />
  <D.Title @text="Integrate with Terraform Cloud" />
  <D.Description @text="Create a new run task in Terraform using the URL and key below." />
  <D.CopyItem @text="https://api.cloud.hashicorp.com" @copyItemTitle="Endpoint URL" />
  <D.CopyItem @text="91ee1e8ef65b337f0e70d793f456c71d91ee1e8ef65b337f0e70d793f456c71d" @copyItemTitle="HMAC Key" />
  <D.CopyItem @isTruncated={{false}} @text="91ee1e8ef65b337f0e70d793f456c71d91ee1e8ef65b337f0e70d793f456c71d" @copyItemTitle="HMAC Key (without truncation)" />
</Hds::Dropdown>

Using the @isTruncated argument, it is possible to disable the truncation applied to the text. Care should be taken in choosing how to use this feature as there are accessibility concerns.

ListItem::Checkmark

For switching context (e.g., organization switchers, project switchers, etc.) use ListItem::Checkmark.

<Hds::Dropdown @listPosition="bottom-left" as |D|>
  <D.ToggleButton @text="HCP Design Sandbox" @color="secondary" />
  <D.Checkmark>ACME Org</D.Checkmark>
  <D.Checkmark @selected={{true}}>HCP Design Sandbox</D.Checkmark>
  <D.Footer @hasDivider={{true}}>
    <Hds::Link::Standalone @icon="list" @text="All Organizations" @color="secondary" @href="#" />
  </D.Footer>
</Hds::Dropdown>

ListItem::Checkbox

For multi-selection within a form or larger filter pattern use ListItem::Checkbox.

<Hds::Dropdown @listPosition="bottom-left" as |D|>
  <D.ToggleButton @count="2" @text="Status" @color="secondary" />
  <D.Checkbox @count="4">Failing</D.Checkbox>
  <D.Checkbox @count="2" checked>Active</D.Checkbox>
  <D.Checkbox @count="1">Starting</D.Checkbox>
  <D.Checkbox @count="3" checked>Pending</D.Checkbox>
  <D.Footer @hasDivider={{true}}>
    <Hds::Button @text="Apply filters" @isFullWidth={{true}} @size="small" />
  </D.Footer>
</Hds::Dropdown>

ListItem::Radio

For single selection within a form or larger filter pattern use ListItem::Radio.

<Hds::Dropdown @listPosition="bottom-left" as |D|>
  <D.ToggleButton @text="Status" @color="secondary" />
  <D.Radio name="status" @count="4">Failing</D.Radio>
  <D.Radio name="status" @count="2" checked>Active</D.Radio>
  <D.Radio name="status" @count="1">Starting</D.Radio>
  <D.Radio name="status" @count="3">Pending</D.Radio>
  <D.Footer @hasDivider={{true}}>
    <Hds::Button @text="Apply filters" @isFullWidth={{true}} @size="small" />
  </D.Footer>
</Hds::Dropdown>

ListItem::Generic

When using the “generic” ListItem, the product team is responsible for implementing the layout and accessibility.

ListItem::Generic allows you to pass custom elements to the Dropdown.

<Hds::Dropdown @listPosition="bottom-left" as |D|>
  <D.ToggleButton @text="Text Toggle" @color="secondary" />
  <D.Title @text="Integrate with Terraform Cloud" />
  <D.Description @text="Create a new run task in Terraform using the URL and key below." />
  <D.Generic>
    <Hds::Link::Standalone @text="Watch tutorial video" @icon="film" @href="/" />
  </D.Generic>
</Hds::Dropdown>

Component API

The Dropdown component is composed of different child components each with their own APIs:

  • The Dropdown component
    • Optional header and footer
  • Toggle components to open/close the Dropdown
    • ToggleButton
    • ToggleIcon
  • ListItem components, to build the Dropdown’s list items
    • Description
    • Generic
    • Interactive
    • Separator
    • Title
<[D].ToggleButton> yielded component
Dropdown::Toggle::Button yielded as contextual component (see below).
<[D].ToggleIcon> yielded component
Dropdown::Toggle::Icon yielded as contextual component (see below).
<[D].Header> yielded component
Dropdown::Header yielded as contextual component (see below).
<[D].Title> yielded component
Dropdown::ListItem::Title yielded as contextual component (see below).
<[D].Description> yielded component
Dropdown::ListItem::Description yielded as contextual component (see below).
<[D].Separator> yielded component
Dropdown::ListItem::Separator yielded as contextual component (see below).
<[D].Interactive> yielded component
Dropdown::ListItem::Interactive yielded as contextual component (see below).
<[D].CopyItem> yielded component
Dropdown::ListItem::CopyItem yielded as contextual component (see below).
<[D].Checkmark> yielded component
Dropdown::ListItem::Checkmark yielded as contextual component (see below).
<[D].Checkbox> yielded component
Dropdown::ListItem::Checkbox yielded as contextual component (see below).
<[D].Radio> yielded component
Dropdown::ListItem::Radio yielded as contextual component (see below).
<[D].Generic> yielded component
Dropdown::ListItem::Generic yielded as contextual component (see below).
<[D].Footer> yielded component
Dropdown::Footer yielded as contextual component (see below).
[D].close function
Function to programmatically close the Dropdown yielded to the content.

If this function is invoked using an {{on "click"}} modifier applied to the ListItem::Interactive element, there is a quirky behavior of the Ember <LinkTo> component which requires a workaround to have the events executed in the right order (this happens only if it has a @route argument). Read more about the issue and a possible solution in this GitHub comment.
listPosition string
  • bottom-left
  • bottom-right (default)
  • top-left
  • top-right
Note: If @enableCollisionDetection is set, the list will automatically flip position to remain visible when near the edges of the screen regardless of the starting placement.
isInline boolean
  • true
  • false (default)
If an @isInline parameter is provided, then the element will be displayed as inline-block (useful to achieve specific layouts like in a container with right alignment). Otherwise, it will have a block layout.
enableCollisionDetection boolean
  • true
  • false (default)
Setting it to true will automatically flip the list position to remain visible when near the edges of the viewport.
isOpen boolean
  • true
  • false (default)
Controls if the list should be rendered initially opened.
width string
any valid CSS width (px, rem, etc)
By default, the Dropdown List has a min-width of 200px and a max-width of 400px, so it adapts to the content size. If a @width parameter is provided then the list will have a fixed width.

We discourage the use of percentage values for this argument. The Dropdown list is a popover element, so relative units use document as a reference (not the parent element), meaning percentage values act similar to vw. If @matchToggleWidth is set, @width is overridden.
height string
any valid CSS height (px, rem, etc)
If a @height parameter is provided then the list will have a max-height.
matchToggleWidth boolean
  • false (default)
Sets the Dropdown List’s width to match the width of the Toggle. It overrides the @width value if set.
preserveContentInDom boolean
  • false (default)
Controls if the content is always rendered in the DOM, even when the Dropdown is closed.
onClose function
Callback function invoked when the Dropdown is closed, if provided.
…attributes
This component supports use of ...attributes.

Contextual components

[D].ToggleButton

The Dropdown::Toggle::Button component, yielded as contextual component.

text string
Required
Text of the ToggleButton. If no text value is defined, an error will be thrown.
color enum
  • primary (default)
  • secondary
size enum
  • medium (default)
  • small
icon string
Acceptable value: any icon name.
count string | number
Displays an optional count indicator using the Badge Count component.
badge string
Displays an optional badge indicator using the Badge component.
badgeIcon string
Appends an icon to the optional badge indicator. Acceptable value: any icon name.
…attributes
This component supports use of ...attributes.

[D].ToggleIcon

The Dropdown::Toggle::Icon component, yielded as contextual component.

text string
Required
Value of aria-label for the ToggleIcon. If no text value is defined, an error will be thrown.
icon string
Acceptable value: any icon name.
hasChevron boolean
  • true (default)
Per design, false is only currently allowed when the "more-horizontal" icon is used; it is set to true by default.
imageSrc string
…attributes
This component supports use of ...attributes.

[D].Header / [D].Footer

The Dropdown::Header / Dropdown::Footer components, yielded as contextual components.

Note: if the Dropdown content exceeds the height of the container, the header and footer remain fixed while the list of items adjusts its height.

yield
Elements passed as children are yielded as inner content of the Dropdown header/footer.
hasDivider boolean
  • false (default)
…attributes
This component supports use of ...attributes.

[D].Title

The Dropdown::ListItem::Title component, yielded as contextual component.

text string
Required
Text to be used for the title. If no text value is defined, an error will be thrown.
…attributes
This component supports use of ...attributes.

[D].Description

The Dropdown::ListItem::Description component, yielded as contextual component.

text string
Required
Text to be used for the description. If no text value is defined, an error will be thrown.
…attributes
This component supports use of ...attributes.

[D].Separator

The Dropdown::ListItem::Separator component, yielded as contextual component.

…attributes
This component supports use of ...attributes.

[D].Interactive

The Dropdown::ListItem::Interactive component, yielded as contextual component.

It internally uses the Hds::Interactive utility component. For more details about this component API, please refer to its documentation page.

yield
Elements passed as children are yielded as inner content of interactive block.
<[I].Badge> yielded component
The Badge component, yielded as contextual component inside interactive blocks of the Dropdown. It exposes the same API as the Badge component.
text string
Required
Deprecated
Text to be used in the item. If no text value is defined and no content is yielded, an error will be thrown.
color enum
  • action (default)
  • critical
Color applied to the text and (optional) icons.
icon string
Leading icon. Acceptable value: any icon name.
trailingIcon string
Trailing icon. Acceptable value: any icon name.
isLoading boolean
  • false (default)
Controls if the item is in “loading” state. When in this state, the item is not actually interactive, but you can pass the other expected arguments for the item (they’re simply ignored).
href
URL passed to the <a> element.
isHrefExternal boolean
  • false (default)
Indicates whether or not the <a> link is external, in which case target="_blank" and rel="noopener noreferrer" attributes are added automatically.
route/models/model/query/current-when/replace
Parameters passed as arguments to the <LinkTo/LinkToExternal> component.
isRouteExternal boolean
  • false (default)
Controls if the “LinkTo” is external to the Ember engine (more details here) in which case it will use a <LinkToExternal> instead of a simple <LinkTo> for the @route.
…attributes
This component supports use of ...attributes.

In this component, the ...attributes are not supported on the root element (an <li> element) but on the underlying element/component (<button>, <a>, <LinkTo> or <LinkToExternal> depending on the @route/@href arguments).

[D].CopyItem

The Dropdown::ListItem::CopyItem component, yielded as contextual component.

It internally uses the Copy::Snippet component. For more details about this component API, please refer to its documentation page.

copyItemTitle string
Displays a title above the text to be copied.
text string
Required
Text to be copied. If no text value is defined, an error will be thrown.

Notice: this argument is forwarded (as textToCopy) to the Copy::Snippet component.
isTruncated boolean
  • true (default)
Constrains text to one line and truncates it based on available width. Text will only be truncated if it does not fit within the available space.

Please be aware there are serious accessibility concerns with using this feature.

Notice: this argument is forwarded to the Copy::Snippet component.

[D].Checkmark

The Dropdown::ListItem::Checkmark component, yielded as contextual component.

yield
Elements passed as children are yielded as inner content of the element.
selected boolean
  • false (default)
Displays a checkmark symbol indicating the current selection.
icon string
Acceptable value: any icon name.
count string | number
Displays an optional count indicator.
href
URL passed to the <a> element.
isHrefExternal boolean
  • false (default)
Indicates whether or not the <a> link is external, in which case target="_blank" and rel="noopener noreferrer" attributes are added automatically.
route/models/model/query/current-when/replace
Parameters passed as arguments to the <LinkTo/LinkToExternal> component.
isRouteExternal boolean
  • false (default)
Controls if the “LinkTo” is external to the Ember engine (more details here) in which case it will use a <LinkToExternal> instead of a simple <LinkTo> for the @route.
…attributes
This component supports use of ...attributes.

In this component, the ...attributes are not supported on the root element (an <li> element) but on the underlying element/component (<button>, <a>, <LinkTo> or <LinkToExternal> depending on the @route/@href arguments).

[D].Checkbox

The Dropdown::ListItem::Checkbox component, yielded as contextual component.

yield
Elements passed as children are yielded as inner content of the element, to be used in the item as label for the input control.
id string
Input control’s id attribute.

By default, the id is automatically generated by the component. Use this argument to pass a custom id.
value string
Input control’s value attribute.
icon string
Acceptable value: any icon name.
count string | number
Displays an optional count indicator.
…attributes
This component supports use of ...attributes.

The attributes will be applied to the <input> element. This means you can use all the standard HTML attributes of the <input> element and all the usual Ember techniques for event handling, validation, etc.

Examples of HTML attributes: name, placeholder, disabled, readonly, required. See the whole list of HTML attributes. Examples of Ember modifiers: {{on "input" [do something]}}, {{on "change" [do something]}}, {{on "blur" [do something]}}.

[D].Radio

The Dropdown::ListItem::Radio component, yielded as contextual component.

yield
Elements passed as children are yielded as inner content of the element, to be used in the item as label for the input control.
id string
Input control’s id attribute.

By default, the id is automatically generated by the component. Use this argument to pass a custom id.
value string
Input control’s value attribute.
icon string
Acceptable value: any icon name.
count string | number
Displays an optional count indicator.
…attributes
This component supports use of ...attributes.

The attributes will be applied to the <input> element. This means you can use all the standard HTML attributes of the <input> element and all the usual Ember techniques for event handling, validation, etc.

Examples of HTML attributes: name, placeholder, disabled, readonly, required. See the whole list of HTML attributes. Examples of Ember modifiers: {{on "input" [do something]}}, {{on "change" [do something]}}, {{on "blur" [do something]}}.

[D].Generic

The Dropdown::ListItem::Generic component, yielded as contextual component.

yield
Elements passed as children are yielded as inner content of the ListItem. When using the “generic” ListItem, the product team is responsible for implementing the layout and accessibility.
…attributes
This component supports use of ...attributes.

Anatomy

Dropdown anatomy

Element Usage
Toggle Required
Header Optional
List Required
Footer Optional

Toggle

Toggle button anatomy Toggle icon anatomy
Element Usage
Text, Icon, or Avatar One is required
Chevron Required, except on the Overflow toggle
Container Required

ListItem

Dropdown ListItem anatomy

Element Usage
Text Required
Icon Required for Critical ListItems; Optional otherwise
Indicator Visible in hover and active state
Focus ring Visible in focus state

States

A note on disabled states

Because disabled states completely remove the interactive function of an element, it can be challenging for a user to understand why it has been disabled and/or why they cannot interact with that element. In an effort to avoid this confusion, we opt for using methods like enabling or hiding the element and, thus, are not offering disabled states for the Dropdown. Read more about when to enable vs hide.

Toggle

Example of dropdown toggle states

ListItem

Interactive

Example of listitem interactive states

Checkbox

Example of listitem checkbox states

Checkmark

Example of listitem checkmark states

Radio

Example of listitem radio states

Conformance Rating

Conditionally conformant

This component is conditionally conformant.

  1. When truncation occurs, a keyboard-only user cannot access the truncated content.
  2. The component is no longer conformant if the chevron icon is removed from the ToggleButton.

Known issues

ToggleIcon with no chevron

Setting @hasChevron to false on ToggleIcons doesn’t provide enough affordance; it’s not quickly seen as actionable.

Color blind users and critical actions

Color blind users, specifically those with Achromatopsia, may have a hard time perceiving Critical ListItems within our Dropdown component.

To provide a more accessible experience, we recommend:

  • Using strong, clear language for the text (e.g., “Delete…”, “Revoke…”, etc.).
  • Adding a relevant icon that indicates the action is destructive (e.g., trash).
  • Moving the Critical ListItem to the bottom of the list or the section.
    • If at the bottom of a list, consider adding a separator above the Critical ListItem to help separate it from other ListItems.
  • Adding a second confirmation layer after the user clicks “Delete” (e.g., showing a confirmation Modal that requires the user to type “Delete” into a field before proceeding).

Keyboard navigation

Example of the focus order for a Dropdown

Applicable WCAG Success Criteria

This section is for reference only. This component intends to conform to the following WCAG Success Criteria:

  • 1.3.1 Info and Relationships (Level A):
    Information, structure, and relationships conveyed through presentation can be programmatically determined or are available in text.
  • 1.3.2 Meaningful Sequence (Level A):
    When the sequence in which content is presented affects its meaning, a correct reading sequence can be programmatically determined.
  • 1.4.1 Use of Color (Level A):
    Color is not used as the only visual means of conveying information, indicating an action, prompting a response, or distinguishing a visual element.
  • 1.4.10 Reflow (Level AA):
    Content can be presented without loss of information or functionality, and without requiring scrolling in two dimensions.
  • 1.4.11 Non-text Contrast (Level AA):
    The visual presentation of the following have a contrast ratio of at least 3:1 against adjacent color(s): user interface components; graphical objects.
  • 1.4.12 Text Spacing (Level AA):
    No loss of content or functionality occurs by setting all of the following and by changing no other style property: line height set to 1.5; spacing following paragraphs set to at least 2x the font size; letter-spacing set at least 0.12x of the font size, word spacing set to at least 0.16 times the font size.
  • 1.4.3 Minimum Contrast (Level AA):
    The visual presentation of text and images of text has a contrast ratio of at least 4.5:1
  • 1.4.4 Resize Text (Level AA):
    Except for captions and images of text, text can be resized without assistive technology up to 200 percent without loss of content or functionality.
  • 2.1.1 Keyboard (Level A):
    All functionality of the content is operable through a keyboard interface.
  • 2.1.2 No Keyboard Trap (Level A):
    If keyboard focus can be moved to a component of the page using a keyboard interface, then focus can be moved away from that component using only a keyboard interface.
  • 2.4.3 Focus Order (Level A):
    If a Web page can be navigated sequentially and the navigation sequences affect meaning or operation, focusable components receive focus in an order that preserves meaning and operability.
  • 2.4.7 Focus Visible (Level AA):
    Any keyboard operable user interface has a mode of operation where the keyboard focus indicator is visible.

Support

If any accessibility issues have been found within this component, let us know by submitting an issue.

4.15.0

Updated

Fixed an issue with the ToggleIcon to make the focus ring visible on mouse click

Aligned private class properties to follow a standardized notation

4.14.0

Updated

Added @matchToggleWidth argument

4.13.0

Updated

Fixed content being preserved in the DOM when closed

Removed the isOpen yielded argument

Added @preserveContentInDom to optionally control rendering of the content

Fixed dropdown content not being preserved when interacted with

Updated the color of the text and icons in the selected state checkmark list item to match the styling of the ListItems (Radio and Checkbox)

4.12.0

Updated

Added the [D].isOpen yielded state, now the content of the Dropdown can be conditionally rendered when it is open.

4.10.0

Updated

The component now yields the Hds::Badge component as a contextual component.

Added @enableCollisionDetection and @isOpen arguments

Replaced the underlying MenuPrimitive with PopoverPrimitive

Deprecated

Deprecated the @text argument. Users are instructed to put text in the yielded block instead.

How to migrate

You can automate this migration using the codemod v4/dropdown-list-item-interactive (see readme file).


Related