## 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.

0 selected

## 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

- Default state uses `<table-toolbar-ui>` — the modern foundation. It already wires Filter / Sort / Columns / Search to the table via `[for]`; don't hand-roll those.
- Bulk bar uses `<toolbar-ui>` with `role="toolbar"` and `aria-label="Bulk actions"`. Match its `--toolbar-py` / `--toolbar-px` to `--table-toolbar-py` / `--table-toolbar-px` so the swap is seamless.
- Both toolbars sit inside the same `<section bleed>` as the table — one surface, flush alignment with the first table cell.
- Selection count leads the bulk bar; `<span data-spacer>` pushes actions right.
- Destructive actions go last and are visually separated with a `<divider-ui vertical>`.
- Keep bulk actions to 3–5; overflow belongs in a `<popover-ui>` "More" menu trailing the divider.
- Drive the swap from the table's `select` event (`detail.selected: number[]`) — toggle `hidden` on each toolbar; don't unmount.