Skip to content

feat: add atomic table components (Release 1 / MLP) - #4940

Draft
gethinwebster wants to merge 6 commits into
mainfrom
dev-v3-gethinw-basic-table-mlp
Draft

feat: add atomic table components (Release 1 / MLP)#4940
gethinwebster wants to merge 6 commits into
mainfrom
dev-v3-gethinw-basic-table-mlp

Conversation

@gethinwebster

@gethinwebster gethinwebster commented Aug 27, 2026

Copy link
Copy Markdown
Member

Summary

Adds the atomic table components (Release 1 / MLP): flat compound parts that give consumers control over individual row and cell rendering, instead of the configuration-driven auto-rendering of Table. Ships GA in cloudscape-design/components.

Parts: TableRoot, TableHead, TableHeaderRow, TableHeaderCell, TableBody, TableRow, TableCell.

API per the API proposal.

API

  • columnLayout?: { type: 'auto' } | { type: 'grid'; columns }auto (content-sized, default) or grid (explicit/proportional widths; the basis for virtualization). Column widths live only on the grid variant, so the correlation is type-enforced.
  • TableRow variant: 'default' | 'selected' | 'shaded' — visual only; the consumer sets ariaSelected explicitly.
  • Curated flat aria* props (Root / Row / HeaderCell) — no blanket aria-* passthrough.
  • disablePaddings on TableCell / TableHeaderCell for exact control columns (e.g. a centered selection control).
  • Fixed-height bring-your-own virtualization via style on TableBody / TableRow.

Reuse with Table

Table composes the atomic TableRow / TableCell as its body <tr> / <td> for the common path (plain-data, selection-control, sticky, wrap-lines, resizable columns). The selection / stripe / divider / padding geometry lives once in _selection-mixins.scss, shared by both Table's body-cell and the atomic cell — one source of truth for the box model. Editable/expandable/treegrid rows, row-header <th>, and header cells stay native.

Deferred (each its own later review)

Grid keyboard navigation (role='grid'), sticky header, bounded internal scroll viewport, column resizing, row expansion, truncation vs wrapping, skeleton loading, grouped columns, auto-measured dynamic row-height virtualization, and id-based column binding.

Testing

  • Unit tests for the atomic parts (roles, aria-label, styling props) plus characterization tests for the Table-reuse selection/stripe paths.
  • Visual & interaction parity verified against Table (selection reflow, control alignment, first/last row, sticky columns): selected rows are constant-height (no row reflow on select).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new GA BasicTable component family (root + structural subcomponents) as a low-level, composable table primitive with shared column layout, optional grid keyboard navigation, and supporting dev pages/test utilities.

Changes:

  • Introduces the headless useBasicTable hook plus compound components (BasicTable*) built on it.
  • Adds BasicTable styling (Cloudscape-tokenized), DOM test-utils wrapper, and comprehensive unit/a11y tests.
  • Adds dev/demo pages showcasing composition patterns (selection, striping, sorting, loading/empty, keyboard scroll) and updates build/test snapshots and pluralization utilities.

Reviewed changes

Copilot reviewed 33 out of 33 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/test-utils/dom/basic-table/index.ts Adds BasicTableWrapper DOM test util helpers.
src/basic-table/use-basic-table.ts Implements headless useBasicTable prop-getters (ARIA + grid template).
src/basic-table/styles.scss Adds tokenized SCSS styling for BasicTable (grid layout, selection, striping, states).
src/basic-table/internal.tsx Implements compound components + auto column sizing + scroll wrapper behavior.
src/basic-table/interfaces.ts Defines public props and internal hook config/types.
src/basic-table/index.tsx Exports the root BasicTable component and props type.
src/basic-table/context.ts Adds context wiring for table, row state, and positional column indices.
src/basic-table/tests/use-basic-table.test.tsx Unit tests for useBasicTable getters + raw-DOM contract proof.
src/basic-table/tests/setup.ts Registers shared a11y matcher for BasicTable tests.
src/basic-table/tests/basic-table.test.tsx Tests compound component rendering + wrapper discoverability.
src/basic-table/tests/basic-table-styling-props.test.tsx Tests styling hooks (selected/striped/selection variant) + auto layout branch.
src/basic-table/tests/basic-table-i18n.test.tsx Tests accessible naming via ariaLabel.
src/basic-table/tests/basic-table-a11y.test.tsx Axe + keyboard navigation + ARIA coherence tests for role=grid.
src/basic-table/tests/stubs/styles-stub.js Adds a styles module stub for tests running from source.
src/basic-table-row/index.tsx Adds top-level BasicTableRow export wrapper.
src/basic-table-header/index.tsx Adds top-level BasicTableHeader export wrapper.
src/basic-table-header-cell/index.tsx Adds top-level BasicTableHeaderCell export wrapper.
src/basic-table-cell/index.tsx Adds top-level BasicTableCell export wrapper.
src/basic-table-body/index.tsx Adds top-level BasicTableBody export wrapper.
src/tests/snapshot-tests/snapshots/test-utils-wrappers.test.tsx.snap Updates generated wrapper snapshots to include BasicTable wrapper APIs.
src/tests/snapshot-tests/snapshots/test-utils-selectors.test.tsx.snap Updates generated selectors snapshot output.
src/tests/snapshot-tests/snapshots/documenter.test.ts.snap Updates documenter snapshot to include BasicTableWrapper method docs.
pages/basic-table/striped-rows.page.tsx Adds dev page demonstrating row striping + selected override.
pages/basic-table/simple.page.tsx Adds basic non-sticky BasicTable dev page.
pages/basic-table/shift-selection.page.tsx Adds dev page demonstrating composed shift-range selection.
pages/basic-table/selection.page.tsx Adds dev page demonstrating composed selection patterns and disabled rows.
pages/basic-table/permutations.page.tsx Adds dev page matrix for role/striped/selected permutations.
pages/basic-table/multi-column-sort.page.tsx Adds dev page demonstrating composed multi-column sort with aria-sort.
pages/basic-table/loading-and-empty.page.tsx Adds dev page showing composed loading/empty rows.
pages/basic-table/keyboard-scroll.page.tsx Adds dev page demonstrating horizontal keyboard scroll region behavior.
pages/basic-table/compact-mode.page.tsx Adds dev page demonstrating inherited compact density styling.
pages/basic-table/common.tsx Adds shared dev-page helpers (columns + header/body renderers).
build-tools/utils/pluralize.js Adds pluralization mapping for BasicTable.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/basic-table/internal.tsx Outdated
});

const columnCount = table.columnCount;
const pageSize = Math.max(1, Math.min(totalRowCount || 1, 100));
Comment thread src/basic-table/internal.tsx Outdated
Comment on lines +292 to +295
role={isScrollable ? 'region' : undefined}
tabIndex={isScrollable ? 0 : undefined}
aria-label={isScrollable ? ariaLabel : undefined}
>
Comment thread src/test-utils/dom/basic-table/index.ts Outdated
Flat compound parts: TableRoot, TableHead, TableHeaderRow, TableHeaderCell,
TableBody, TableRow, TableCell. Table composes the atomic Row/Cell for its body
hot path (plain-data, selection-control, sticky, wrap, resizable), sharing the
selection/stripe/divider geometry via _selection-mixins so there is a single
source of truth.

- columnLayout: { type: 'auto' } (default) | { type: 'grid', columns }
- TableRow variant: 'default' | 'selected' | 'shaded' (visual only)
- curated flat aria props; disablePaddings on TableCell/TableHeaderCell
- fixed-height bring-your-own virtualization via style props on Body/Row
@gethinwebster gethinwebster changed the title feat: add BasicTable (Release 1 / MLP) feat: add atomic table components (Release 1 / MLP) Sep 8, 2026
TableBody/TableRow no longer walk or clone their children to flag the last
row. The last-row divider suppression and selected-last-row height
compensation move to a positional :last-child rule in table-body styles,
scoped under .body so the Table-reuse path (plain <tbody>) is unaffected.
Shared cell padding constants are extracted to table-cell/constants so both
modules stay in lock-step. This is composition-safe and drops the
cloneElement machinery.
Mirror the status-indicator internal-component idiom across all 7 parts:
- named exported InternalTable<X>Props interface (extends the public props +
  InternalBaseComponentProps); internal-only flags live inside it
- uniform InternalTable<X> naming (was InternalRoot + bare Head/Body/Row/Cell)
- default-export function with destructured params + getBaseProps(rest)
- value-style props re-export in index.tsx, default-importing the internal
- table-cell's separate internal props interface merged into the single
  InternalTableCellProps (dual-consumer substrate note kept)

Also drops fluff comments and regenerates the two stale generated-artifact
snapshots (documenter Style.height Property.Height collapse; the dedup-dropped
classic body-cell test-utils selector). Behavior-neutral: no public API, DOM, or
CSS change.
@codecov

codecov Bot commented Sep 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.15385% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.66%. Comparing base (e404a45) to head (148dcd0).

Files with missing lines Patch % Lines
src/table/body-cell/td-element.tsx 79.41% 7 Missing ⚠️
src/table-root/internal.tsx 87.50% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4940      +/-   ##
==========================================
- Coverage   97.67%   97.66%   -0.01%     
==========================================
  Files         960      983      +23     
  Lines       31376    31572     +196     
  Branches    11597    11681      +84     
==========================================
+ Hits        30645    30834     +189     
- Misses        724      731       +7     
  Partials        7        7              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants