selection and bulk actions
In a long list, people often want to do the same thing to many items: grab eight episodes, restart three workloads, archive forty old items. Doing that one row at a time is slow, and easy to get wrong. So people first select the rows, by ticking their checkboxes, and then act on all of them at once, with a bulk action.
The data table and the selection toolbar do this; their pages show them live, and this pattern's React page has the whole thing to try.
when it fits
- When people act on many rows the same way.
- In a worklist, where the list is the work and its toolbar holds what to do with it.
- When some rows can't take the action right now: they stay in the list, can't be ticked, and say why.
It isn't the right tool:
- For one action on one row. Use the row's menu, or let a press open the row. People shouldn't have to select a row to act on it.
- For choosing values in a form, like the volumes a backup includes. Use checkboxes or a multi select: a form's values are saved with the form, not acted on at once.
- For narrowing a list. Use the filters. Selecting rows hides nothing.
- For records nobody acts on. A short list to read needs no selection at all.
selection modes
Pick how a list selects by the actions it has, not by habit.
| mode | when | what changes |
|---|---|---|
| None | The list has no bulk actions | Nothing: a press on a row opens it |
| Single | A list next to the detail of the row that is chosen | The chosen row is highlighted; there are no checkboxes |
| Multiple | The list has actions that apply to several rows at once | A column of checkboxes appears; nothing else changes |
Today the data table does two of the three: none, and multiple. Single selection, a list beside its detail, is planned.
press versus select
Pressing a row and ticking it do different things, and people shouldn't have to wonder which one they are about to do.
- A press opens, the checkbox selects. No spot does both.
- When a row has nothing to open, in a list with checkboxes, a press anywhere on it ticks its checkbox.
Today the data table keeps the two apart as described. The › at the end of a row that opens isn't drawn yet: it is planned.
anatomy
- The selection toolbar. It takes the place of the list's title bar. With nothing selected, it says what the list holds: “40 missing”. With a selection, it shows the count in blue, “8 selected”, a way to clear it, and, when it helps, “select all 37”.
- The emphasized action. The toolbar's one blue button, with the count in its label: “grab 8 selected”. It is only there while something is selected.
- Other actions. Quieter buttons, or items in the toolbar's “more” menu, which is always there when the toolbar is narrow.
- The select-all checkbox in the table's header. It selects every row on the screen.
- A checkbox on each row, named after the row: “select S04E07”. A selected row is tinted, with a blue bar on its edge.
- A menu on each row, at its end, named after the row: “actions for S04E07”.
- A group's row and its action. The group's name and count, and one small, quiet button that acts on the whole group: “grab all 9”.
- Rows that can't be selected. A greyed-out checkbox, and a status that says why: “on its way”.
- The confirmation. A toast that counts what happened: “8 episodes queued”.
select all
- The header checkbox selects the rows that are loaded and match the filters. The toolbar then offers the rest, “select all 2,409”, and its count always says which of the two is in effect.
- After select all, the count says exactly what will be acted on: “2,409 selected”, not just “all”. The button says the same number: “grab 2,409 selected”.
- The header checkbox shows a dash while some rows are selected but not all, and a tick when all of them are. Pressing it while it shows a tick clears the selection.
- Offering “select all 2,409” matters most right after the header checkbox. That is the moment people wonder whether they have only these rows, or all of them.
Today the header checkbox selects every row on the screen, but not the rows past “show more”, or in collapsed groups. The app decides when to offer “select all”.
the selection toolbar
- It takes the title bar's place while something is selected, with the count, “clear”, and the actions. With nothing selected, it is the list's title bar again.
- One emphasized action: the one people use most, labelled with a verb, what it acts on, and the count. The count keeps it honest: people check it before they press.
- An action that only works for some of the selected rows stays available. It acts on those it can, and says what it skipped: “6 queued · 2 already on their way”.
- An action that can be undone runs at once, without asking. One that deletes, or can't be undone, asks first, in a dialog with the count in its title and on its button.
per-row actions
- One menu per row, at its end, with that row's actions: “grab now”, “search again”. Buttons on every row repeat the same labels all the way down, and bury the content.
- Name the menu after its row. Grey out an item that doesn't apply to a row, rather than leaving it out, so every row's menu has the same shape.
- A row's own action doesn't clear the selection. If it leaves its row unselectable, that row drops out of the selection.
group actions
- A group's row can carry one action for the whole group, as a small, quiet button. A button like “grab all 9” acts on the rows of the season that can be grabbed, and its label counts them.
- Leave the action out when it would act on nothing.
- A group's action works without a selection, and pressing it doesn't tick the group.
after the action
- Update the rows. Their status shows the new state, “on its way”. Keep the rows people just acted on in the list, unless the list is defined by the old state, like a “needs attention” tab; then say that they left.
- Clear the selection the action used. The toolbar goes back to its title, and a screen reader hears “selection cleared”.
- Confirm in a toast that counts what happened, and what didn't and why: “6 episodes queued · 2 skipped: on their way already”.
- Count skipped rows; don't hide them. Rows get skipped when their state changed after they were selected, or when a service refuses some.
- When the action fails, or partly fails and people need to do something, say so in a banner above the list, with a way forward, not in a toast. See message handling.
rows that can't be selected
- Keep them in the list with a greyed-out checkbox, and say why in their status: “on its way”. Every way of selecting leaves them out, select all and ranges included.
- Don't hide the checkbox or the row. People need to see that the row is there, and why it is left out.
keeping a selection
- Sorting, showing more and refreshing keep it.
- Filtering keeps it too. Rows hidden by a filter stay selected, and the toolbar says so: “8 selected · 3 hidden by filters”.
- Leaving the view clears it, and so does a finished bulk action, which says its result in a toast.
Today the data table keeps whatever selection the app gives it; keeping or clearing it is up to the app. Nothing counts the rows a filter hides yet; the toolbar can show that count when the app keeps it. The worklist's live example is older than this rule: it unselects a row as soon as a filter hides it.
keyboard
The toolbar is one stop for the Tab key, and the table's rows are another; the header's controls, select all and the sort buttons, are stops of their own in between. From a row, Tab goes on into its checkbox and its menu.
| where | key | what it does |
|---|---|---|
| Table | ↑ and ↓, Home and End, Page Up and Page Down | Moves between rows |
| Table | Space | Ticks or unticks the row |
| Table | Shift and a click, Shift+Space, Shift+↑ or Shift+↓ | Selects a range, from the last row ticked |
| Table | Ctrl+A or Cmd+A | Selects every loaded row that matches the filters |
| Table | Esc | Clears the selection |
| Table | Tab | Goes into the row's checkbox and menu |
| Toolbar | ← and →, Home and End | Moves between the toolbar's controls, round and round |
| Row menu | Enter, Space or ↓ | Opens it on its first item; ↑ opens it on its last |
| Row menu | Esc | Closes it, and the focus goes back to its button |
Today Ctrl+A or Cmd+A selects every row on the screen, like the header checkbox, and Esc doesn't clear the selection yet: it is planned.
accessibility
- Names. Each checkbox: “select S04E07”. The header checkbox: “select every visible row”. Each menu: “actions for S04E07”. The toolbar: the list's name, “missing episodes”.
- What is read out. The toolbar reads each change of the count once, politely: “8 selected”, “selection cleared”. The toast is read out too, and never takes the focus. The table says nothing about the selection as a whole; each row says whether it is selected.
- Not by colour alone. The checkbox carries the selection; the row's tint and its blue bar only add to it.
- The focus stays put when the button people pressed goes away. Pressing “clear”, “select all” or the bulk action removes that button; the toolbar then holds the focus itself. When a group's action disappears, or a focused row leaves the list, the focus moves to the table.
Today the header checkbox's name, and the word “select” before each row's label, are in English only.
the words
- The count. “8 selected”, with thousands separators: “2,500 selected”.
- The bulk action. A verb, what it acts on, and the count: “grab 8 selected”, “restart 3 workloads”. Not “ok”, “apply” or “submit”.
- Select all. The number that will be selected: “select all 2,500”.
- Hidden rows. The count after the selection: “8 selected · 3 hidden by filters”.
- Clear. “clear”.
- The toolbar's title. What the list holds: “2,500 missing”, “40 workloads”.
- Row menu items. A verb for the one row: “grab now”, “search again”.
- Group actions. The count they act on: “grab all 9”.
- The toast. What happened, counted, in the items' own words, then what was skipped and why. Not “done”, “success” or “action completed”.
- Why a row can't be selected. Its status, in the item's words: “on its way”, “held”. Not “disabled” or “n/a”.
related
- Data table: the selection in full, with its keys, ranges and select all.
- Toolbar and selection toolbar: the selection toolbar's parts and states.
- Toast: saying what happened.
- Message handling: what to say when an action goes wrong.
- Interaction: the keyboard model every component shares.