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.
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.
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
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
.
Header
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.
Footer
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.
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, useCheckbox
. - Use
Checkbox
for multi-selection within a form or larger filter pattern. - Use
Radio
for single selection within a form or larger filter pattern.
Use Checkmark
for context switching.
Don't use Checkmark
instead of Radio
in larger filter patterns.
Non-interactive
Non-interactive ListItems help provide structure and context to a Dropdown. Types include: Description
, Loading
, Separator
, and Title
.
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.
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.
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.
Use icons consistently and when they reinforce the content.
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.
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.
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.
<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.
List footer
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>
Rendering a link with @href
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
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
Dropdown
<[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
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
@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)
@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)
true
will automatically flip the list position to remain visible when near the edges of the viewport.
isOpen
boolean
- true
- false (default)
width
string
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
@height
parameter is provided then the list will have a max-height.
matchToggleWidth
boolean
- false (default)
@width
value if set.
preserveContentInDom
boolean
- false (default)
onClose
function
…attributes
...attributes
.
Contextual components
[D].ToggleButton
The Dropdown::Toggle::Button
component, yielded as contextual component.
text
string
color
enum
- primary (default)
- secondary
size
enum
- medium (default)
- small
icon
string
count
string | number
badge
string
badgeIcon
string
…attributes
...attributes
.
[D].ToggleIcon
The Dropdown::Toggle::Icon
component, yielded as contextual component.
text
string
aria-label
for the ToggleIcon. If no text value is defined, an error will be thrown.
icon
string
hasChevron
boolean
- true (default)
false
is only currently allowed when the "more-horizontal" icon is used; it is set to true
by default.
imageSrc
string
…attributes
...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
hasDivider
boolean
- false (default)
…attributes
...attributes
.
[D].Title
The Dropdown::ListItem::Title
component, yielded as contextual component.
text
string
…attributes
...attributes
.
[D].Description
The Dropdown::ListItem::Description
component, yielded as contextual component.
text
string
…attributes
...attributes
.
[D].Separator
The Dropdown::ListItem::Separator
component, yielded as contextual component.
…attributes
...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
interactive
block.
<[I].Badge>
yielded component
Badge
component, yielded as contextual component inside interactive
blocks of the Dropdown
. It exposes the same API as the Badge
component.
text
string
color
enum
- action (default)
- critical
icon
string
trailingIcon
string
isLoading
boolean
- false (default)
href
<a>
element.
isHrefExternal
boolean
- false (default)
<a>
link is external, in which case target="_blank"
and rel="noopener noreferrer"
attributes are added automatically.
route/models/model/query/current-when/replace
<LinkTo/LinkToExternal>
component.
isRouteExternal
boolean
- false (default)
<LinkToExternal>
instead of a simple <LinkTo>
for the @route.
…attributes
...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
text
string
Notice: this argument is forwarded (as
textToCopy
) to the Copy::Snippet
component.
isTruncated
boolean
- true (default)
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
selected
boolean
- false (default)
icon
string
count
string | number
href
<a>
element.
isHrefExternal
boolean
- false (default)
<a>
link is external, in which case target="_blank"
and rel="noopener noreferrer"
attributes are added automatically.
route/models/model/query/current-when/replace
<LinkTo/LinkToExternal>
component.
isRouteExternal
boolean
- false (default)
<LinkToExternal>
instead of a simple <LinkTo>
for the @route.
…attributes
...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
id
string
id
attribute.
By default, the
id
is automatically generated by the component. Use this argument to pass a custom id
.
value
string
value
attribute.
icon
string
count
string | number
…attributes
...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
id
string
id
attribute.
By default, the
id
is automatically generated by the component. Use this argument to pass a custom id
.
value
string
value
attribute.
icon
string
count
string | number
…attributes
...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
…attributes
...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.
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).