Conversation
Adds `/data-table-selection` to the vite example: 240 vendor records with a checkbox column, and a footer that swaps its row-count text for a bulk-action bar while a selection is open. The bar reuses the same `DataTable.Pagination` in both states, so the right-hand cluster is identical whether or not rows are selected. Inversion is done by re-pointing the surface tokens on a wrapper inside the footer, so the pagination buttons, the page-size Select and the action Buttons re-theme themselves without any class overrides. Prototype only — nothing under packages/** changes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
Code Metrics Report
Details | | main (ecc3f93) | #496 (75cb5da) | +/- |
|---------------------|----------------|----------------|------|
| Coverage | 87.1% | 87.1% | 0.0% |
| Files | 178 | 178 | 0 |
| Lines | 5467 | 5467 | 0 |
| Covered | 4764 | 4764 | 0 |
+ | Test Execution Time | 2m7s | 2m3s | -4s |Reported by octocov |
…t or as a pattern Records the footer direction for multi-select bulk actions, notes that `catalogue/src/pattern/interaction/multi-select` currently prescribes a floating bottom bar (built on raw Table.Root, predating DataTable selection) and so needs rewriting either way, and frames the open question for a team call: build the bar into DataTable via `selectionActions`, or keep it a documented pattern. No decision taken. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
itsprade
force-pushed
the
feat/data-table-footer-selection-actions
branch
from
September 3, 2026 14:56
a473622 to
9a6439b
Compare
Brings the prototype up to date with main (58 commits, incl. the generic Toolbar #559 and the docs-src pipeline #396). main moved every demo page under pages/showcase/ (#513), so the prototype moves with them, unchanged: /data-table-selection -> /showcase/data-table-selection, listed in the sidebar's Showcase group. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…kbox Selection persists across pages, but the header checkbox did not respect that: checking it replaced the selection with the current page's rows, and unchecking it cleared every page. With 5 rows picked on page 1, select-all on page 2 gave 25 selected instead of 30. The header checkbox is now page-scoped in both directions. selectAllRows adds the page's rows to the selection, and a new deselectAllRows removes only the page's rows; clearSelection still empties everything. deselectAllRows is optional on DataTableContextValue, and a hand-built context without it falls back to clearSelection. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…oss pages Adds the data half of footer bulk actions (#1738): a selectionActions option on useDataTable, shaped like rowActions, and the selected rows it acts on. The footer bar that renders these actions follows in the next commit. - SelectionAction: id, label, icon, variant, and an optional appliesTo(row) predicate that narrows an action to the selected rows it applies to. onClick receives those rows plus a clearSelection helper. - A non-empty selectionActions array enables row selection on its own, so onSelectionChange stays optional. - selectedRows: selection is now an ordered map of id -> row as last seen, so rows picked on other pages can still be counted and handed to an action. Rows on the current page always win over the remembered copy. selectedRows is required on UseDataTableReturn, like expandedIds, and optional on DataTableContextValue, which is documented as hand-constructible. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rows are selected With selectionActions set and at least one row selected, the footer becomes the bulk-action bar (#1738): the count, the actions, and Clear, with the footer's own children (usually Pagination) kept alongside. Tables without selectionActions render exactly as before. - Built on the generic Toolbar (#559): the bar is a Toolbar.Row, so it gets role=toolbar and Arrow/Home/End navigation between its buttons. - The first three actions render as buttons; the rest collapse into a "More actions" menu that opens upward. An action with appliesTo shows its eligible count ("Activate (6)") and disables at zero. - Surface: bg-accent, which stays soft in every theme and both modes. A display:contents wrapper re-points --accent and --muted-foreground so hover states and secondary text stay visible on the tinted bar. - Sticky while open, so on a page-scrolling table the bar rides the bottom of the viewport until the table's end scrolls into view. The DataTable root moves from overflow-hidden to overflow-clip for this: both clip to the rounded frame, but hidden also makes the root a scroll container, which trapped the sticky footer inside the table. - Pagination hides its own "N selected" text while the bar is up and shares the line with it, dropping to a second line only when it doesn't fit. - A persistent polite live region announces the count from the first tick; when the bar closes with focus inside it, focus returns to the header checkbox. Labels in en and ja. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
/showcase/data-table-selection was the #496 prototype: a hand-built footer bar on useDataTableContext with a primary/neutral tone toggle. It now uses the real API, so the page shows exactly what the core component does: - selectionActions with appliesTo counts, Activate / Deactivate / Export inline and Delete in the More actions menu behind a confirm dialog (interaction/confirm) - actions mutate local state, so counts and badges update after an action - the generic Toolbar scaffold on top, matching the other DataTable demos - a Pinned footer / Page scroll switch to compare <Layout fill> with a page- scrolling table, where the bar rides the bottom of the window dashboard/products drops its ad-hoc "Selected: …" line for Publish / Archive / Delete bulk actions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lect pattern - DataTable docs: a Selection actions section (with accessibility notes), a SelectionAction reference table, the selectionActions option, and the footer/pagination and useDataTableContext notes that go with it. - interaction/multi-select: rewritten around selectionActions. The floating bar on a hand-built Table.Root with native checkboxes is gone, along with its dangling source marker; the example is a DataTable with an appliesTo action, an overflowed destructive action, and a confirm dialog. - list/dense-scan: bulk actions point at the footer bar. - decisions: #496's open question is now a decided record — built into DataTable, what changed from the first sketch (appliesTo instead of count, rows instead of ids, accent instead of primary/neutral), and follow-ups. - changeset: minor, calling out the page-scoped header checkbox. Generated docs/ and the manifest come from pnpm docs:sync. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
itsprade
marked this pull request as ready for review
September 29, 2026 12:02
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this does
Adds bulk actions to
DataTable(tailor-inc/platform-planning#1738). PassselectionActionstouseDataTableand, while rows are selected,DataTable.Footerbecomes a bulk-action bar: the selection count, your actions, and Clear, with pagination kept alongside. When nothing is selected, the footer looks exactly as it does today.This PR started as the prototype and open question from 3 Sep. The direction was settled with Sean in #pf-app-shell and at the 18 Sep board planning: build it into DataTable, place it in the footer, and let the consumer control which actions appear.
API
It is one option, shaped like
rowActions. There is nothing new to compose in JSX.SelectionActionid,label,iconvariant"default" | "destructive". This is styling only; the app still confirms destructive actions itself (interaction/confirm).appliesToonClick.onClick(rows, { clearSelection })New on the return value and context:
selectedRows(each selected row as last loaded, across pages) anddeselectAllRows(page-scoped). The new type isSelectionAction.Behaviour
selectionActions, aDataTable.Footer, and at least one selected row.selectionActionsalso turns on the checkbox column by itself, soonSelectionChangebecomes optional.<Layout fill>the footer is already pinned. On a page-scrolling table, the bar isposition: stickywhile rows are selected, so it rides the bottom of the viewport and settles back into place at the end of the table. There is no JS.Toolbar(feat: add generic toolbar #559). The bar is aToolbar.Row, so it getsrole="toolbar"and Arrow/Home/End navigation.accent, which stays soft in all three themes and in both light and dark mode. Hover and secondary text are re-pointed so they stay legible on the tinted bar.Compatibility
selectionActionsrender exactly as before, and a test asserts this. New context members are optional.selectedRowsis required onUseDataTableReturn, likeexpandedIdswas, so only a hand-built return value would need it.clearSelectionstill empties everything. Tables whose selection stays on one page see no difference. The fix is its own commit (dcc9e77) so it can be split out if preferred, and the changeset calls it out.overflow-hiddentooverflow-clip. Both clip the toolbar to the rounded frame, buthiddenalso makes the root a scroll container, which pinned the sticky footer inside the table.clipkeeps your clipping without that side effect.Commits
fix(data-table): the header checkbox keeps other pages' rows.feat(data-table):selectionActionsand remembered selected rows. Selection becomes an ordered map of id → row as last seen, and the current page's copy wins.feat(data-table): the footer bar (selection-bar.tsx), plus the Pagination and Footer changes and en/ja labels.feat(examples):/showcase/data-table-selectionmoves onto the real API, and/dashboard/productsreplaces its "Selected: …" line with bulk actions.docs(data-table): docs-src sections and theSelectionActiontable;interaction/multi-selectis rewritten aroundselectionActions, since the floating bar on a rawTable.Rootis gone;list/dense-scanis updated;decisions/data-table-selection-footer-actions.mdis now Decided; and a minor changeset.The earlier commits on this PR are the original prototype and a merge of
main.Worth discussing
appliesTo(row)replaces the consumer-suppliedcountfrom the first sketch. Selection spans pages, and an app with server pagination can't count rows on other pages without its own cache. The table already sees every row the user selects.rowSelection. With a controlled selection, rows that haven't loaded yet are counted once they load; this is documented. Whichever lands second adapts, and the row memory just goes wherever selection is written.Follow-ups (not in this PR)
DataTable.SelectionActionsfor custom placement, following the "option = default placement, sub-component = custom placement" rule from tailor-inc/platform-planning#1699.Try it
/showcase/data-table-selection: 240 vendors. Tick rows, page with a selection open, open ⋯ → Delete, and use the Pinned footer / Page scroll switch./dashboard/products: Publish / Archive / Delete bulk actions.Verification
selection-bar.test.tsx(13 new), plus hook tests (cross-page selection,selectedRows,selectionActions) and a header-checkbox test. 1,842 core tests pass.pnpm fmt:check,pnpm exec turbo run lint test type-check check-dts(28/28),pnpm docs:check, and docs examples compile against core.🤖 Generated with Claude Code