A dropdown displays a list of links or actions for the user to choose from. It should not to be confused with a select element which is used in forms as a way for the user to select an option from a list.
When to use
- To display a list of actions under a single button toggle.
When not to use
- In forms. When providing more than 5–7 options in a form, use a Select instead.
- When selecting an option results in immediate navigation or update to the page content, use a Context Switcher (coming soon).
ToggleButton Size
ToggleButtons come in two sizes: small and medium. This allows for placement in ButtonSets with buttons of the same size.
Small
Medium
Chevron
Open toggles use a chevron pointing up, while closed toggles use a chevron pointing down.
Open
Closed
ToggleIcon
Chevrons indicate that ToggleIcon opens the list, so they’re required for all variations. The only (temporary) exception is the overflow menu, which uses the “more-horizontal” icon.
List
Placement
Right (default)
Left
List Size
Default width
The default List has a min-width of 200px and a max-width of 400px.
This means if there’s a list item with a lot of text (i.e., Description), the list will automatically expand up to 400px to accommodate the content of the widest list item.
Fixed width
If you do not want the width of the List to expand automatically to accommodate the widest list item, you can indicate a specific width.
As a best practice, we do not recommend lists wider than 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 list container is automatically determined based on the contents within the list.
- Integrate with Terraform Cloud
- Create a new run task in Terraform using the URL and key below.
-
Endpoint URL
-
HMAC Key
- Manage
ListItem Types
Icons
Icons in ListItems are optional.
We recommend letting the text speak for itself unless an icon provides additional value.
Ask yourself, “Which icon should I use here?” If the answer isn’t obvious within 5 seconds, consider whether the icon is really providing additional value.
- About
- Automate with Terraform
Critical
While icons are optional, we recommend using a relevant icon for Critical ListItems. Using the right icon provides a stronger/more immediate visual indication that the action is destructive. See the section on color blind users and critical actions (internal link) for more details about making these actions more accessible.
Content
General
We recommend using dropdowns only to display a list of links or actions. A dropdown should not be a catch-all used to squeeze a lot of content into a small, contained area. A crowded dropdown is difficult for the user to parse and can result in a poor user experience.
If you find that you need additional custom content in the dropdown, please reach out to the HDS team (internal link) to discuss alternative options.
ListItems
There is no character limit for interactive ListItems, but we recommend keeping them short and concise (~36 characters).
How to use this component
To make the invocation more intuitive for developers, we’ve provided contextual components for toggles and list items. For example, <Hds::Dropdown::ListItem::Separator />
is yielded in a hash, using the key <XX.Separator />
when invoked:
<Hds::Dropdown as |dd|>
<dd.ToggleButton @text="Menu" />
<dd.Title @text="Title Text" />
<dd.Description @text="Descriptive text goes here." />
<dd.Interactive @href="#" @text="Add" />
<dd.Interactive @href="#" @text="Add More" />
<dd.Interactive @href="#" @text="Add Another Thing Too" />
<dd.Separator />
<dd.Interactive @route="components" @icon="trash" @text="Delete" @color="critical" />
</Hds::Dropdown>
ListItem::Interactive
The Interactive
list item renders the correct element based on the passing of an @route
, @href
, or the addition of a click event (i.e.,
{{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:
<Doc::ListContainer class="hds-dropdown-list">
<Hds::Dropdown::ListItem::Interactive @text="Run command" />
</Doc::ListContainer>
Rendering a link with @href
If you pass a @href
argument, a link (<a>
element) will be generated:
<Doc::ListContainer class="hds-dropdown-list">
<Hds::Dropdown::ListItem::Interactive @href="https://www.hashicorp.com/request-demo/terraform" @text="Request a demo" />
</Doc::ListContainer>
Rendering a LinkTo (with @route
)
If you pass a @route
, Ember’s <LinkTo>
will be used:
<Doc::ListContainer class="hds-dropdown-list">
<Hds::Dropdown::ListItem::Interactive @route="my.page.route" @model="my.page.model" @text="Activate cluster" />
</Doc::ListContainer>
If the route is external to your current engine, you must also pass @isRouteExternal=true
to the component so that it will use <LinkToExternal>
instead of a <LinkTo>
. For more details see the Hds::Interactive component documentation.
All the standard arguments for the <LinkTo/LinkToExternal>
components are supported (eg. models/model/query/current-when/replace
).
Examples
ToggleButton + ListItem, Separator
This example shows a dropdown with a toggle-button, links, a separator and a link (color, critical):
<Hds::Dropdown as |dd|>
<dd.ToggleButton @text="Text Toggle" />
<dd.Interactive @route="components" @text="Item One" />
<dd.Interactive @route="components" @text="Item Two" />
<dd.Interactive @route="components" @text="Item Three" />
<dd.Interactive @text="Item Four (closes on click)" />
<dd.Separator />
<dd.Interactive @route="components" @text="Delete" @color="critical" @icon="trash" />
</Hds::Dropdown>
Rendered (positioned to the right):
ToggleButton + Title, Description, CopyItem, Separator
This example demonstrates the use of a dropdown with a toggle-button (color, secondary), title, description, a generic (which is yielding a Link::Standalone component), copy-item, a separator and a link (color, critical):
To indicate that a secondary button style should be used for the "button" toggle, add @color="secondary"
. If no @color
is declared, primary
will be used by default.
<Hds::Dropdown as |dd| >
<dd.ToggleButton @text="Integrate with Terraform Cloud" @color="secondary" />
<dd.Title @text="Integrate with Terraform Cloud" />
<dd.Description @text="Create a new run task in Terraform using the URL and key below." />
<dd.Generic>
<Hds::Link::Standalone @text="Watch tutorial video" @icon="film" href="/" />
</dd.Generic>
<dd.CopyItem @text="https://api.cloud.hashicorp.com" @copyItemTitle="Endpoint URL" />
<dd.CopyItem @text="91ee1e8ef65b337f0e70d793f456c71d" @copyItemTitle="HMAC Key" />
</Hds::Dropdown>
ToggleIcon for "overflow" dropdown menus
Example: an "overflow" toggle for use only in a table element (per design). The dropdown has default and destructive (critical) links. This is the only use case where it is acceptable to use
@hasChevron=false
.
Note that toggleText
is still required–it provides the aria-label
for the toggle button.
<Hds::Dropdown as |dd|>
<dd.ToggleIcon @icon="more-horizontal" @text="Overflow Options" @hasChevron= />
<dd.Interactive @route="components" @text="Create" />
<dd.Interactive @route="components" @text="Read" />
<dd.Interactive @route="components" @text="Update" />
<dd.Separator />
<dd.Interactive @route="components" @text="Delete" @color="critical" @icon="trash" />
</Hds::Dropdown>
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., checking asynchronously the user’s permission to execute a certain operation, once the toggle has been clicked).
In that case the argument @isLoading=true
can be passed to the item: this will show a "loading" icon (even if an argument @icon
is provided) and set the item as non-interactive until the value of @isLoading
is set to false
again.
<Hds::Dropdown as |dd|>
<dd.ToggleIcon @icon="more-horizontal" @text="Overflow Options" @hasChevron= />
<dd.Interactive @route="components" @isLoading= @text="Edit cluster" @color="action" @icon="edit" />
<dd.Interactive @route="components" @text="Delete" @color="critical" @icon="trash" />
</Hds::Dropdown>
ToggleIcon as user menu
In this example, we have a user icon with a title, description, separator, and links.
Note that toggleText
is still required, because it supplies the aria-label
for the toggle button.
<Hds::Dropdown as |dd|>
<dd.ToggleIcon @icon="user" @text="user menu" />
<dd.Title @text="Signed In" />
<dd.Description @text="email@domain.com" />
<dd.Separator />
<dd.Interactive @route="components" @text="Settings and Preferences" />
<dd.Interactive @route="components" @text="Delete" @color="critical" @icon="trash" />
</Hds::Dropdown>
Rendered as a toggle/icon for a user menu (positioned to the right):
Here is a customized example to demonstrate how that would look like in dark mode (not supported by the design system yet):
ToggleIcon with other icons
In this example, we have a settings icon with a title, description, separator, and links.
Note that toggleText
is still required, because it supplies the aria-label
for the toggle button.
<Hds::Dropdown as |dd|>
<dd.ToggleIcon @icon="settings" @text="settings menu" />
<dd.Title @text="Signed In" />
<dd.Description @text="email@domain.com" />
<dd.Separator />
<dd.Interactive @route="components" @text="Settings and Preferences" />
<dd.Interactive @route="components" @text="Delete" @color="critical" @icon="trash" />
</Hds::Dropdown>
Component API
The Hds::Dropdown
component is composed of different child components, each with their own APIs:
- The Dropdown component
- Toggle components to open/close the dropdown
- ToggleButton
- ToggleIcon
- ListItem components, to build the dropdown’s list items
- Description
- Generic
- Interactive
- Separator
- Title
Dropdown
- Name
-
listPosition
- Type
-
string
- Values
-
- left
- right (default)
- Name
-
width
- Type
-
string
- Values
- any valid CSS width (px, rem, etc)
- Description
-
By default the dropdown list has a
min-width
of200px
and amax-width
of400px
applied to it, so it adapts to the content size. If a@width
parameter is provided then the list will have a fixed width.
- Name
-
close
- Type
-
function
- Description
-
Function that can be called to programmatically close the dropdown. If this function is invoked using an
{{on "click"}}
modifier applied to theListItem::Interactive
element, there is a quirky behavior of the Ember<LinkTo>
component that will require some 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.
- Name
-
onClose
- Type
-
function
- Description
- Callback function invoked when the dropdown is closed (if provided).
- Name
-
…attributes
- Description
-
This component supports use of
...attributes
.
Toggle::Button
- Name
-
text
- Type
-
string
- Required
-
Required
- Description
- The text of the toggle button. If no text value is defined, an error will be thrown.
- Name
-
color
- Type
-
enum
- Values
-
- primary (default)
- secondary
- Name
-
size
- Type
-
enum
- Values
-
- medium (default)
- small
- Name
-
…attributes
- Description
-
This component supports use of
...attributes
.
Toggle::Icon
- Name
-
text
- Type
-
string
- Required
-
Required
- Description
-
The value of
aria-label
for the toggle icon. If no text value is defined, an error will be thrown.
- Name
-
icon
- Type
-
string
- Description
- Acceptable value: any icon name.
- Name
-
hasChevron
- Type
-
boolean
- Values
-
- false
- true (default)
- Description
-
Per design,
false
is only currently allowed when the "more-horizontal" icon is used; it is set totrue
by default.
- Name
-
imageSrc
- Type
-
string
- Name
-
…attributes
- Description
-
This component supports use of
...attributes
.
ListItem::CopyItem
- Name
-
copyItemTitle
- Type
-
string
- Name
-
text
- Type
-
string
- Required
-
Required
- Description
- The text to be copied. If no text value is defined, an error will be thrown.
ListItem::Description
- Name
-
text
- Type
-
string
- Required
-
Required
- Description
- The text to be used for the description. If no text value is defined, an error will be thrown.
- Name
-
…attributes
- Description
-
This component supports use of
...attributes
.
ListItem::Generic
- Name
-
yield
- Description
- Elements nested within this child component are yielded inside the list item. When using the "generic" list item the developer is completely responsible for any element yielded, including the accessibility of that element, as well as the layout of the content (we provide only the horizontal padding for consistency with the other items).
- Name
-
…attributes
- Description
-
This component supports use of
...attributes
.
ListItem::Interactive
- Name
-
text
- Type
-
string
- Required
-
Required
- Description
- The text to be used in the item. If no text value is defined, an error will be thrown.
- Name
-
color
- Type
-
enum
- Values
-
- action (default)
- critical
- Description
- Acceptable values:
- Name
-
icon
- Type
-
string
- Description
- Acceptable value: any icon name.
- Name
-
isLoading
- Type
-
boolean
- Values
-
- false (default)
- true
- Description
- This 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).
- Name
-
href
- Description
-
This is the URL passed to the
<a>
element.
- Name
-
isHrefExternal
- Type
-
boolean
- Values
-
- false (default)
- true
- Description
-
This indicates whether or not the
<a>
link is external; in these cases,target="_blank"
andrel="noopener noreferrer"
attributes are added automatically.
- Name
-
route models model query current-when replace
- Description
-
These are the parameters passed as arguments to the
<LinkTo/LinkToExternal>
component.
- Name
-
isRouteExternal
- Type
-
boolean
- Values
-
- false (default)
- true
- Description
-
This 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.
- Name
-
…attributes
- Description
-
This component supports use of
...attributes
.
In this component, the...attributes
are not spread on the root element of the component (an<li>
element) but on the underlying element/component (<button>
,<a>
,<LinkTo>
or<LinkToExternal>
depending on the@route/@href
arguments).
ListItem::Separator
- Name
-
…attributes
- Description
-
This component supports use of
...attributes
.
ListItem::Title
- Name
-
text
- Type
-
string
- Required
-
Required
- Description
- The text to be used for the title. If no text value is defined, an error will be thrown.
- Name
-
…attributes
- Description
-
This component supports use of
...attributes
.
Dropdown Anatomy
Element | Usage |
---|---|
Toggle | Required |
List | Required (only visible when open) |
Toggle Anatomy
Button
Icon
ListItem Anatomy
Element | Usage |
---|---|
Text | Required |
Icon | Required for Critical ListItems, otherwise optional. |
Indicator | Visible in hover and active state |
Focus ring | Visible in focus state |
CopyItem Anatomy
Element | Usage |
---|---|
Title | Optional |
Text | Required |
Copy Icon | Required |
Focus ring | Visible in focus state |
States
Button
Icon
ListItem
Conformance Rating
This component is conditionally conformant.
- In any instance where data truncation occurs, there is no current method to access that data for the keyboard-only user.
- If the chevron icon is removed from the dropdown’s toggle button, the component is no longer conformant.
Best Practices
Color blind users (specifically those with Achromatopsia) may have a hard time perceiving Critical ListItems within our dropdown. To provide a more accessible experience, we recommend:
- Using strong, clear language for the text (e.g., “Delete…”, “Revoke…”, etc.)
- Adding a relevant icon
- 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” (ie. showing a confirmation modal that requires the user to type “Delete” into a field before proceeding)
Keyboard navigation
Many types of users rely on their keyboard to navigate the web, so it’s important that our designs have annotations for the focus order (how keyboard users navigate the web) to ensure we’re providing them with a natural path and great experience.
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, please let us know by submitting an issue.