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

Table Multi-select

Guidelines, compositions, and interaction patterns for selecting and transforming results in a Table.

The Helios Table multi-select functionality supports performing bulk actions and selection of one or more rows within a Table.

Example of Table multi-select in context

These guidelines are meant to assist teams in designing and building Tables that have bulk editing and selection functionality. Currently there aren’t Ember or Figma components to support these advanced patterns, but they can be composed using a combination of HDS components.

Selected count

Display the selected count to communicate how many rows or results have been selected in the entire data set. This includes Table rows that are outside of the current view in the Table (e.g., in a different page if using Pagination), and should be represented using a numerical value.

Example of the selected count

Pair this with a message to clearly communicate that a selection has been made. This can be a simple generic message stating "{selected count} selected", or can be more specific to the type of object in the data set (e.g., a user, cluster, workspace, etc).

Generic and specific messaging

Total count

If technically feasible, communicate the selected count as a portion of the total count, or total number of results in the Table. This can give the user a better overall snapshot of what they have selected and how the selection compares to the entire data set. This can also more effectively communicate that there may be results that are selected across multiple pages.

Total count of items and count of selected items

Bulk actions

Bulk actions allow the user to edit, delete, or transform one or more results in a Table. Consolidate these actions in a small Dropdown inline with the selected count, message, and total count.

Example of bulk actions

For Table instances requiring a single action (like bulk deletion), use a small Button instead of a Dropdown. We advise using either secondary or critical Buttons, based on the action’s intent.

Example of a single action

Editing results

With a selection made, consider using a Modal to perform bulk edits or updates to parameters of the selected results. This is generally appropriate for editing five parameters or less; for more complex scenarios, consider shifting the editing experience to a separate page.

Editing results in a Modal

Deleting results

Deleting or performing destructive actions on results should use an additional confirmation to ensure that only the intended results are affected. Use a critical Modal to communicate the number of results affected and what consequences might occur from deletion.

Deleting results in a Modal

Bulk selection

Bulk selection is global in scope, meaning that all results in the data set are affected, even those outside of the current view. Consolidate these functions in a Dropdown paired with bulk actions.

Note: This type of selection is not a replacement for the selection in the header of the Table. Where the selection is made implies a different scope and is handled by different UI elements.

Examples of bulk selection include:

  • Select all: Select all of the results in a data set.
  • Reset selection: Take the current selected results and deselect them.
  • Select inverse: Deselect the currently selected results; select those that are currently deselected.

Example of bulk selection


Multi-select anatomy

Element Usage
Selected count Displays the number of selected items in the table.
Selected message Communicates that results in the table have been selected.
Total results Displays the total number of results in the data set.
Actions trigger Recommended to use either a secondary or critical Button for single actions, or a secondary Dropdown for multiple actions.
Bulk actions Consolidates multiple bulk actions into a single element.
Bulk selection Consolidates multiple selection functions into a single element.


Multi-select pattern

Within the Multi-select pattern itself, use a 16px horizontal gap between the message and the actions.

Spacing within the multi-select pattern

In context

When combining a Multi-select pattern with filtering and similar functions acting on Table data, use a 16px vertical gap between rows of related elements.

Spacing in context with other elements


For a basic Table (e.g., one that doesn’t use filtering), place the selection pattern above the top-right corner of the Table.

A basic multi-select example in context

Layout with a filter pattern

When composing a Multi-select pattern together with a Filter bar and Applied filters, maintain the same placement.

Multi-select with a Filter Pattern

Putting it all together

Multi-select in a more complex scenario


As the viewport width shrinks, stack the elements around the Table and filter pattern in a single column.

Example of reflow at a smaller viewport

When combining a Multi-select table with filtering, sorting, or pagination, you may encounter complex scenarios regarding how selected results should be persisted across pages and what the user expects when traversing large data sets.

These interaction guidelines are not fully comprehensive. They should instead be considered as conversation starters between design and engineering on how best to optimize the user experience.

If you run into unique scenarios that these guidelines don’t account for, we would love to hear about them through our normal support channels.

Consistent communication

To help prevent unnecessary editing or deleting and to ensure users are interacting with the results they intend to, it is vital to consistently communicate their selections, or the existence of a selection, at all times.

Persisting this communication in the selected count can help to avoid mishaps, but it may also be necessary to confirm with the user prior to making changes that cannot be reversed.

Example of a double confirmation

Selection scope

Where a selection is made in the UI can imply differences in how the selection is scoped, and can be broken down into three different levels of hierarchy.

  1. Global scope: Selection applies to all rows in the table and is made via bulk selection in the Multi-select pattern.
  2. Page-level scope: Selection applies to all rows in the current page of a paginated table and is made via the Checkbox in the Table header.
  3. Row-level scope: Selection applies only to a single row, result, or item in a Table, and is made via the checkbox at the start of the row.

Selection scope

Persisting the selection

One of the most common questions around Multi-select patterns stems from when and how selected results are persisted when a user performs different actions on a Table. Consider the following scenario:

A user is viewing a Table displaying a data set consisting of 10,000 results. In order to make changes to specific results, the user may take the following actions:

  1. Filter the Table to display only a subset of the results.
  2. Sort the Table by a specific parameter to order the results in a meaningful way.
  3. Traverse through multiple pages of the Table through Pagination.

If not handled in a clear and logical manner, how the selection is persisted across all of these actions can be confusing and open the user up to making unintended changes if what they have selected is persisted (or not persisted).

Within a paginated Table

If a user makes a selection on one page of a paginated Table and progresses to the next page, persisting this selection can be communicated by the selected count and can be helpful in scenarios where much of the data is similar or overlaps.

When filtering Table results

Filtering a data set is a reductive action that removes results from being displayed within a Table. This impacts multiple areas of the interface while raising a number of considerations around persisting the selection.

Consider these topics as conversation starters to help make an informed decision about the user experience. The answers may vary depending on product architecture and broader application strategy.

  • In a Multi-select pattern, should the total count change to reflect a reduction in the number of visible results?
  • In Pagination, is the number of results reduced to reflect those excluded by the filter?
  • If a selection has been made prior to filtering, is the selected state persisted even if the filtered results are excluded from the data set?
  • Are there any parameters in the data set that are variable in nature? E.g., status that is prone to changing if a cluster is starting up or spinning down.

In all of these scenarios, it is important to clearly and consistently communicate what results have been selected and what impact a change will have on them.

Not persisting the selection

Depending on the scenario, it might not make sense or even be possible to persist the selection in a meaningful way, e.g., if filtering the data set results in a new fetch request that resets the state of the application. If this is the case, consider resetting the selection after each alteration to the Table.

It is the responsibility of consumers to implement this pattern and to ensure that all accessibility success criteria are met or exceeded.

Aria role

Due to its dynamic nature, updates to the selected count must be announced to those using assistive technology. This can be done by adding role=status to the element containing the count.

This is a representative example of how this could be accomplished using HDS components and role=status to announce changes in the UI. Test it yourself by enabling VoiceOver and incrementing the selectedCount with the "Add to count" button.

10 selected out of 100

<div class="doc-table-multi-select-role-example">
  <button {{on "click" this.updateSelectedCount}}>Add to count</button>
  <div class="doc-table-multi-select-pattern-wrapper">
    <Hds::Text::Body role="status" @tag="p" @size="200" @color="foreground-primary" >
      {{this.selectedCount}} selected out of {{this.totalCount}}
    <Hds::Dropdown as |D|>
      <D.ToggleButton @size="small" @text="Actions" @color="secondary" />
      <D.Interactive @text="Edit" @icon="edit" />
      <D.Interactive @text="Delete" @icon="trash" @color="critical" />
      <D.Separator />
      <D.Interactive @text="Select all" />
      <D.Interactive @text="Reset selection" />