A dropdown is a flexible component that displays a list of actions or options to the user. It should not to be confused with Select, which is used in forms as a way for the user to make a selection from a list.
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.
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.
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.
Size
Default width
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 that content before the content wraps.
- Signed in as
- name@email.com
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 have set the maximum width to 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.
- Integrate with Terraform Cloud
- Create a new run task in Terraform using the URL and key below.
-
Endpoint URL
-
HMAC Key
- Manage
ListItem
Types
Icon usage
Icons in ListItems are optional, and we recommend letting the text speak for itself unless an icon provides additional value.
We don’t recommend mixing and matching icon use; that’s to say, if using an icon in one ListItem, use an icon in all ListItems. Doing so keeps the text aligned so the eye can scan the list of options more easily.
- About
- About
Critical ListItems
Icons in Critical ListItems
While icons are optional, we recommend using a relevant icon for Critical ListItems. Using the correct icon provides a stronger and more immediate visual indication that the action is destructive. Read more about how color blind users see critical actions in our UIs.
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 type “Delete” into a field before proceeding). This safeguards against accidental clicks by requiring users to confirm the destructive action.
Content
There is no character limit for ListItems, but we recommend keeping them short and concise (~36 characters).
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.
How to use this component
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 <dd.Separator />
.
<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>
List position
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 |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>
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= @listPosition="bottom-right" as |dd|>
<dd.ToggleButton @text="Text Toggle" @color="secondary" />
<dd.Interactive @route="components" @text="Item One" />
<dd.Interactive @route="components" @text="Item Two" />
<dd.Interactive @route="components" @text="Item Three" />
</Hds::Dropdown>
</div>
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 |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>
Alternatively, pass secondary
to @color
to display a secondary button with a chevron icon.
<Hds::Dropdown as |dd|>
<dd.ToggleButton @text="Text Toggle" @color="secondary" />
<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>
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 |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>
ToggleIcon as user menu
@text
is still required, because it supplies the aria-label
for ToggleIcon.
<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>
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 |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>
ListItem::Interactive
ListItem::Interactive
renders the correct element based on the passing of an @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:
<Doc::ListContainer class="hds-dropdown__list">
<Hds::Dropdown::ListItem::Interactive @text="Run command" />
</Doc::ListContainer>
Rendering a link with @href
If you pass an @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
)
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
).
<Doc::ListContainer class="hds-dropdown__list">
<Hds::Dropdown::ListItem::Interactive @route="my.page.route" @model="my.page.model" @text="Activate cluster" />
</Doc::ListContainer>
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 |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>
ListItem::Generic
ListItem::Generic
allows you to pass custom elements to the Dropdown.
<Hds::Dropdown as |dd|>
<dd.ToggleButton @text="Text Toggle" @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>
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
Dropdown
- Name
-
listPosition
- Type
-
string
- Values
-
- bottom-left
- bottom-right (default)
- top-left
- top-right
- 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
, so it adapts to the content size. If a@width
parameter is provided then the list will have a fixed width.
- Name
-
height
- Type
-
string
- Values
- any valid CSS width (px, rem, etc)
- Description
-
If a
@height
parameter is provided then the list will have a fixed height.
- Name
-
isInline
- Type
-
boolean
- Default
-
- false (default)
- Description
-
If a
@isInline
parameter is provided then the element will be displayed asinline-block
(useful to achieve specific layouts like in a container with right alignment). Otherwise it will be have ablock
layout.
- Name
-
close
- Type
-
function
- Description
-
Function 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 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.
- Name
-
onClose
- Type
-
function
- Description
- Callback function invoked when the Dropdown is closed, if provided.
- Name
-
…attributes
- Description
-
This component supports use of
...attributes
.
Dropdown::Header and Dropdown::Footer
If the Dropdown content exceeds the height of the container, the header and footer remain fixed while the list of items adjusts its height.
- Name
-
yield
- Description
- Elements nested in this child component are yielded inside the Dropdown header/footer.
- Name
-
hasDivider
- Type
-
boolean
- Default
-
- false (default)
- Name
-
…attributes
- Description
-
This component supports use of
...attributes
.
Toggle::Button
- Name
-
text
- Type
-
string
- Required
-
Required
- Description
- Text of the ToggleButton. 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
-
icon
- Type
-
string
- Description
- Acceptable value: any icon name.
- Name
-
count
- Type
-
string
- Description
- Displays an optional count indicator using the Badge Count component.
- Name
-
badge
- Type
-
string
- Description
- Displays an optional badge indicator using the Badge component.
- Name
-
badgeIcon
- Type
-
string
- Description
- Appends an icon to the optional badge indicator. Acceptable value: any icon name.
- Name
-
…attributes
- Description
-
This component supports use of
...attributes
.
Toggle::Icon
- Name
-
text
- Type
-
string
- Required
-
Required
- Description
-
Value of
aria-label
for the ToggleIcon. 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
- Default
-
- 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::Interactive
- Name
-
text
- Type
-
string
- Required
-
Required
- Description
- 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: “action” or “critical”.
- Name
-
icon
- Type
-
string
- Description
- Acceptable value: any icon name.
- Name
-
isLoading
- Type
-
boolean
- Default
-
- false (default)
- Description
- 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
-
URL passed to the
<a>
element.
- Name
-
isHrefExternal
- Type
-
boolean
- Default
-
- false (default)
- Description
-
Indicates whether or not the
<a>
link is external, in which casetarget="_blank"
andrel="noopener noreferrer"
attributes are added automatically.
- Name
-
route/models/model/query/current-when/replace
- Description
-
Parameters passed as arguments to the
<LinkTo/LinkToExternal>
component.
- Name
-
isRouteExternal
- Type
-
boolean
- Default
-
- false (default)
- Description
-
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 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).
ListItem::Title
- Name
-
text
- Type
-
string
- Required
-
Required
- Description
- 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
.
ListItem::Description
- Name
-
text
- Type
-
string
- Required
-
Required
- Description
- 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::Separator
- Name
-
…attributes
- Description
-
This component supports use of
...attributes
.
ListItem::CopyItem
- Name
-
copyItemTitle
- Type
-
string
- Name
-
text
- Type
-
string
- Required
-
Required
- Description
- Text to be copied. If no text value is defined, an error will be thrown.
ListItem::Checkmark
- Name
-
yield
- Description
- Content to be used in the item.
- Name
-
selected
- Type
-
boolean
- Default
-
- false (default)
- Description
- Displays a checkmark symbol indicating the current selection.
- Name
-
icon
- Type
-
string
- Description
- Acceptable value: any icon name.
- Name
-
count
- Type
-
string
- Description
- Displays an optional count indicator.
- Name
-
href
- Description
-
URL passed to the
<a>
element.
- Name
-
isHrefExternal
- Type
-
boolean
- Default
-
- false (default)
- Description
-
Indicates whether or not the
<a>
link is external, in which casetarget="_blank"
andrel="noopener noreferrer"
attributes are added automatically.
- Name
-
route/models/model/query/current-when/replace
- Description
-
Parameters passed as arguments to the
<LinkTo/LinkToExternal>
component.
- Name
-
isRouteExternal
- Type
-
boolean
- Default
-
- false (default)
- Description
-
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 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).
ListItem::Checkbox
- Name
-
yield
- Description
- Content to be used in the item as label for the input control.
- Name
-
value
- Type
-
string
- Description
-
Input control’s
value
attribute.
- Name
-
icon
- Type
-
string
- Description
- Acceptable value: any icon name.
- Name
-
count
- Type
-
string
- Description
- Displays an optional count indicator.
- Name
-
id
- Type
-
string
- Description
-
Input control’s
id
attribute.
By default, theid
is automatically generated by the component. Use this argument to pass a customid
.
- Name
-
…attributes
- Description
-
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:id
,name
,value
,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]}}
.
ListItem::Radio
- Name
-
yield
- Description
- Content to be used in the item as label for the input control.
- Name
-
value
- Type
-
string
- Description
-
Input control’s
value
attribute.
- Name
-
icon
- Type
-
string
- Description
- Acceptable value: any icon name.
- Name
-
count
- Type
-
string
- Description
- Displays an optional count indicator.
- Name
-
id
- Type
-
string
- Description
-
Input control’s
id
attribute.
By default, theid
is automatically generated by the component. Use this argument to pass a customid
.
- Name
-
…attributes
- Description
-
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:id
,name
,value
,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]}}
.
ListItem::Generic
- Name
-
yield
- Description
- Elements nested in this child component are yielded inside the ListItem. When using the “generic” ListItem, the product team is responsible for implementing the layout and accessibility.
- Name
-
…attributes
- Description
-
This component supports use of
...attributes
.
Anatomy
Dropdown
Element | Usage |
---|---|
Toggle | Required |
Header | Optional |
List | Required |
Footer | Optional |
Toggle
Element | Usage |
---|---|
Text, Icon, or Avatar | One is required |
Chevron | Required, except on the Overflow toggle |
Container | Required |
ListItem
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
Toggle
ListItem
Interactive
Checkbox
Checkmark
Radio
Conformance Rating
This component is conditionally conformant.
- When truncation occurs, a keyboard-only user cannot access the truncated content.
- 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
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.