designmotionhq

interaction

Bulk Actions

Bulk actions are a system, not a lone checkbox.

Watch on Instagram

Key insights

  • The header checkbox needs three states: empty, partial, and checked. The indeterminate dash is not optional, and partial always resolves to select-all, never to clear.
  • Name the number. When select-all only grabs the rows on screen, offer 'Select all 247 matching' instead of a bare 'all' that hides the true scope.
  • Keep the count honest as context shifts. Change a filter and the label should re-read live (from 247 matching down to 96) so people act on the real set.
  • Selection is state, not the DOM. Shift-click picks a range, and the selected ids survive paging because they live in application state, not in the visible rows.
  • For destructive bulk actions, skip the confirm modal. Echo the count, run the action immediately, and offer a 10 second undo with a draining countdown ring.

Do / Don't

  • Do: Give the header checkbox all three states and let the partial dash resolve to select-all.
  • Do: Spell out the exact count in the affordance, like 'Select all 247 matching'.
  • Do: Swap destructive confirm dialogs for an undo window that echoes what you deleted.
  • Don't: Ship a two-state header checkbox that skips the indeterminate dash.
  • Don't: Label bulk selection with a vague 'all' that hides how many rows you touched.
  • Don't: Store the selection in the DOM, where it silently resets the moment someone changes page.

Want Claude to build this correctly?

UX Engine gives Claude Code the senior-designer reasoning behind every pattern.

The Design System Blueprint

An 11-page visual guide to consistent, scalable UI: colors, typography, spacing, components, motion.

Get the Blueprint — free

The PDF, plus emails about new patterns and my tools. Unsubscribe anytime.

Related patterns