Bulk Action Toolbar

table-toolbar-ui toolbar-ui table-ui

When a table has row selection, swap the standard <table-toolbar-ui> for a contextual bulk-action bar at the same surface position. Selection count anchors the left, actions flow from the right, destructive action last.

When to use

Any table where users act on multiple rows at once: archive, delete, export, move. Swapping the toolbar (rather than stacking a second bar) keeps the surface compact and signals "selection mode" with the strongest possible affordance — the chrome itself changes.

Toolbar swap on selection

Tick the checkboxes below — the default <table-toolbar-ui> swaps for the bulk-action bar at the same height. Untick to return.

Anatomy

Both toolbars sit inside the same <section bleed> so they share one surface. Toggle visibility on the select event from the table.

<card-ui> <section bleed> <!-- Default state — modern foundation --> <table-toolbar-ui for="resources" text="Resources" count="6"></table-toolbar-ui> <!-- Bulk action bar — swaps in when rows are selected --> <toolbar-ui data-bulk-bar hidden role="toolbar" aria-label="Bulk actions"> <text-ui strong><span data-bulk-count>0</span> selected</text-ui> <span data-spacer></span> <button-ui text="Archive" icon="archive" variant="ghost" size="sm"></button-ui> <button-ui text="Export" icon="download-simple" variant="ghost" size="sm"></button-ui> <button-ui text="Move" icon="folder-simple" variant="ghost" size="sm"></button-ui> <divider-ui vertical></divider-ui> <button-ui text="Delete" icon="trash" variant="ghost" size="sm"></button-ui> </toolbar-ui> <table-ui id="resources" selectable sortable></table-ui> </section> </card-ui> // Wire the swap. table-ui dispatches 'select' with detail.selected (number[]). const table = document.getElementById('resources'); const tbar = document.querySelector('table-toolbar-ui'); const bulk = document.querySelector('[data-bulk-bar]'); const countEl = bulk.querySelector('[data-bulk-count]'); table.addEventListener('select', (e) => { const n = e.detail.selected?.length ?? 0; countEl.textContent = String(n); tbar.hidden = n > 0; bulk.hidden = n === 0; });

Rules