feat: add composable low-level table components (TableRoot, TableHead, TableRow, TableCell, and more) - #4977
feat: add composable low-level table components (TableRoot, TableHead, TableRow, TableCell, and more)#4977gethinwebster wants to merge 2 commits into
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4977 +/- ##
========================================
Coverage 97.66% 97.67%
========================================
Files 960 985 +25
Lines 31368 31551 +183
Branches 11592 11638 +46
========================================
+ Hits 30637 30817 +180
- Misses 724 727 +3
Partials 7 7 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
4e53624 to
7a55898
Compare
There was a problem hiding this comment.
🟡 Changes recommended
ARIA counts and multi-sort semantics are incorrect, capped flex sizing drops weights, and the PR title violates the required format.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (2)
src/table-root/internal.tsx:43
aria-rowcountcounts every row in the accessibility tree, including the header. This API describesariaRowcountas the number of data rows, andTableRow.ariaRowindexstarts data rows at 2, so forwarding the value unchanged makes the last virtualized row's index exceed the declared count (the demo declares 10,000 but reaches row index 10,001). Add the header row when emitting the attribute, as the existing Table does insrc/table/table-role/table-role-helper.ts:36-40, and update the assertions accordingly.
src/table-root/use-table-root.ts:27- Supplying
maxWidthsilently discards a flexible column'ssize.flex: for example, flex weights 1 and 2 both compile to the sameminmax(..., 300px)track. This contradicts the documented proportionalsizebehavior while the public type permits the combination. Either preserve the weight in the capped-track implementation or makemaxWidthandsize.flexmutually exclusive in the type and documentation.
- Files reviewed: 61/61 changed files
- Comments generated: 2
- Review effort level: Balanced
7a55898 to
f9668ba
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Shared context leaks into nested high-level tables, and auto-layout edge rows can shift when selection changes.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 62/62 changed files
- Comments generated: 3
- Review effort level: Balanced
| const { columnLayout } = useTableContext(); | ||
| const variant = useRowVariant(); | ||
| const isVisualRefresh = useVisualRefresh(); |
| const { columnLayout } = useTableContext(); | ||
| const isVisualRefresh = useVisualRefresh(); | ||
| const isGrid = columnLayout.type === 'grid'; | ||
| const mergedNativeAttributes = isGrid ? { ...nativeAttributes, role: 'columnheader' as const } : nativeAttributes; |
f9668ba to
fe931fd
Compare
fe931fd to
b811703
Compare
b811703 to
7177e9b
Compare
There was a problem hiding this comment.
🟡 Changes recommended
The scroll viewport is not keyboard-accessible, and selected-row outlines are incorrect when grid tracks overflow.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 62/62 changed files
- Comments generated: 2
- Review effort level: Balanced
There was a problem hiding this comment.
🟡 Changes recommended
Grid rows can lose column alignment, and reserved variant attributes can be overridden by consumer data attributes.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 62/62 changed files
- Comments generated: 3
- Review effort level: Balanced
| const selectedDataAttribute = variant === 'selected' ? { 'data-variant-selected': 'true' } : undefined; | ||
| const shadedDataAttribute = variant === 'shaded' ? { 'data-variant-shaded': 'true' } : undefined; |
| min-inline-size: 100%; | ||
| inline-size: max-content; |
| const scrollRegionProps = isScrollable | ||
| ? { | ||
| role: ariaLabel || ariaLabelledby ? ('region' as const) : undefined, | ||
| tabIndex: 0, | ||
| 'aria-label': ariaLabel, |
…aderCell/Body/Row/Cell) Public atomic table components built on internal substrates extracted from the existing Table, plus the shared cell-base geometry partial, demo pages, unit tests, and generated test-utils/documenter snapshots.
…ell dedup Delegate the existing Table's td/th elements to InternalTableCell/ InternalTableHeaderCell (atomic-default-on, with disableContentWrapper/ disableDivider/suppressBlock*Placeholder opt-outs for the classic path), extract shared cell geometry into the cell-base partial, migrate first/last-row edges to positional CSS, and fix atomic-grid selection-control centering. Also regenerate the generated-artifact snapshots and fix the test-utils finder pluralization for the new components.
What this adds
A set of low-level, composable table components —
TableRoot,TableHead,TableHeaderRow,TableHeaderCell,TableBody,TableRow, andTableCell. They let a consumer assemble a table from primitives, as a lower-level alternative to the existing high-levelTablecomponent.How they are built
Rather than reimplementing table cell and row markup and styling from scratch — which would risk drifting visually from the existing
Table— these components are built on the same internal building blocks the existingTablealready uses for its own cells and rows. The existingTableis refactored to compose those same building blocks.The result is a single shared implementation of the cell/row box model and its visual states (selection, shading, dividers, spacing), instead of two implementations that could diverge over time.
Effect on the existing Table
The existing
Tablerenders exactly as before. The refactor only changes which internal pieces it composes, not the markup or styles it produces. The new components' additional styling is keyed on markers the existingTablenever sets, so the shared styles are reused (not duplicated) and stay inert for the existingTable.Verification
Tableis confirmed visually unchanged across selection, striping, sticky columns, inline editing, loading/empty, footer, and grouped-header states.Tableoutput — including selection-control alignment and the absence of any content shift when a row's selection is toggled.Notes for reviewers
Tableto build on the shared internals.