Skip to content

feat: add automatic skeleton rows to Table - #4772

Open
gethinwebster wants to merge 11 commits into
mainfrom
dev-v3-gethinw-table-auto-skeleton-rows
Open

feat: add automatic skeleton rows to Table#4772
gethinwebster wants to merge 11 commits into
mainfrom
dev-v3-gethinw-table-auto-skeleton-rows

Conversation

@gethinwebster

@gethinwebster gethinwebster commented Jul 23, 2026

Copy link
Copy Markdown
Member

Adds automatic skeleton-row sizing to Table via skeleton={{ totalRows: 'auto' }}: during loading the table fills its available viewport with placeholder rows, and a post-render correction removes rows if the rendered page would overflow (never below one row).

Changes

  • Automatic skeleton rows in use-auto-skeleton-rows.ts, wired through Table internals and interfaces.
  • Unit + browser integration coverage: sticky header, footer, wrapLines on/off with long headers, and mixed data + skeleton rows (data rows always precede skeleton rows).
  • AppLayout console-shell dev pages (#/light/app-layout/auto-skeleton-table, ...-nowrap) with an external #h header and #f footer, matching a real console layout.

Testing

  • npm run build, npm run lint, and the table unit suites (17/17) pass.
  • Browser integration tests run in CI.
  • Row-count oscillation risk was investigated with a real headless-Chrome probe (forced overflow, container churn, seed-height mismatch) — no oscillation and no ResizeObserver-loop warnings.

@gethinwebster gethinwebster changed the title Table: fix auto skeleton row overflow + layout coverage feat: add automatic skeleton rows to Table Jul 23, 2026
@gethinwebster
gethinwebster force-pushed the dev-v3-gethinw-table-auto-skeleton-rows branch from 5ba3e9e to 6978122 Compare July 23, 2026 07:22
@codecov

codecov Bot commented Jul 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.79518% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 97.63%. Comparing base (f97729a) to head (c8e171c).
⚠️ Report is 12 commits behind head on main.

Files with missing lines Patch % Lines
src/table/use-auto-skeleton-rows.ts 98.46% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4772      +/-   ##
==========================================
+ Coverage   97.61%   97.63%   +0.01%     
==========================================
  Files         952      957       +5     
  Lines       30816    31097     +281     
  Branches    11318    11435     +117     
==========================================
+ Hits        30081    30361     +280     
- Misses        688      689       +1     
  Partials       47       47              

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

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds an “auto” mode for Table skeleton rows so loading states can fill the available vertical viewport with placeholder rows, including a post-render overflow correction and coverage across unit + browser integration scenarios.

Changes:

  • Introduces useAutoSkeletonRows and wires it into Table rendering so skeleton={{ totalRows: 'auto' }} computes skeleton row count from viewport constraints (optionally capped via maxAutoRows).
  • Extends the public skeleton configuration type and updates feature-metrics reporting for auto mode.
  • Adds unit + browser integration tests plus dev/demo pages to validate behavior with nested scroll containers, sticky header/footer, wrapLines, mixed data+skeleton rows, and AppLayout page chrome.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/table/use-auto-skeleton-rows.ts New hook to measure available viewport space and compute/correct skeleton row count.
src/table/internal.tsx Integrates auto skeleton row calculation into Table rendering and refs.
src/table/interfaces.tsx Updates SkeletonConfig to support 'auto' + maxAutoRows and documents the new options.
src/table/index.tsx Updates component metadata reporting to distinguish fixed vs automatic skeleton configuration.
src/table/tests/table-feature-metrics.test.tsx Adds unit coverage for metrics emitted by automatic vs fixed skeleton config.
src/table/tests/skeleton.test.tsx Adds unit coverage for auto sizing, overflow correction, caps, and ordering with data rows.
src/table/integ/skeleton.test.ts Adds browser integration coverage for nested scroll viewports, features, mixed rows, and AppLayout chrome.
src/internal/utils/scrollable-containers.ts Adds getScrollableParents utility used for viewport detection.
src/tests/snapshot-tests/snapshots/documenter.test.ts.snap Updates generated docs snapshot for the new union type + docs text.
pages/table/skeleton-rows.page.tsx Adds a dev-page toggle to switch between fixed and auto skeleton rows.
pages/table/auto-skeleton-rows.page.tsx New dev page exercising auto skeleton rows across layout permutations.
pages/app-layout/auto-skeleton-table.page.tsx New dev page validating auto skeleton rows inside AppLayout with external header/footer.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

* Returns the element's ancestors whose computed `overflow-y` is `auto` or `scroll`,
* ordered nearest-first. These are the ancestors capable of producing a vertical scrollbar.
*/
export function getScrollableParents(element: HTMLElement): HTMLElement[] {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we have a test for this?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

implicitly, but now added an explicit test too

Comment thread src/table/interfaces.tsx Outdated
export interface SkeletonConfig {
totalRows: number;
}
export type SkeletonConfig = { totalRows: number; maxAutoRows?: never } | { totalRows: 'auto'; maxAutoRows?: number };

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

can we do union types that are named in the namespace for these instead of inline one, it'll make it more readable I think? Just like we do for ColumnDisplayProperties = ColumnDisplay | GroupDisplay; Maybe something like AutoConfig and FixedConfig or AutoSkeletonConfig,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

good point, updated

@NathanZlion
NathanZlion self-requested a review July 27, 2026 13:52

import { getScrollableParents } from '../internal/utils/scrollable-containers';

const AUTO_SKELETON_VIEWPORT_BUFFER = 16;

This comment was marked as resolved.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

In my testing it needed a certain amount of buffer away from the bottom to prevent often over-shooting with measurements because things shift around the page a little during loading. So no specific reason for this number rather than another close number, but some buffer is needed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Comment thread src/table/use-auto-skeleton-rows.ts Outdated
Comment thread src/table/interfaces.tsx Outdated
Comment on lines +70 to +72
* - `totalRows` ('auto') - The number of skeleton rows is calculated from the available viewport height.
* - `maxAutoRows` (number) - Limits the number of rows rendered when `totalRows` is set to `'auto'`.
* - `minAutoRows` (number) - Sets the minimum number of rows rendered when `totalRows` is set to `'auto'`.
NathanZlion
NathanZlion previously approved these changes Jul 27, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Comment thread src/table/use-auto-skeleton-rows.ts Outdated
Comment on lines +97 to +121
const minRowsValue = Math.max(1, minRows ?? 1);
const [rows, setRows] = useState(minRowsValue);
const rowHeightRef = useRef<number>();

const updateRows = useCallback(() => {
if (!enabled) {
return;
}

const tableRoot = tableRootRef.current;
const tableWrapper = tableWrapperRef.current;
const skeletonRows = tableBodyRef.current?.querySelectorAll<HTMLElement>(SKELETON_ROW_SELECTOR);
const firstSkeletonRowRect = skeletonRows?.[0]?.getBoundingClientRect();
const lastSkeletonRowRect = skeletonRows?.[skeletonRows.length - 1]?.getBoundingClientRect();
const rowHeight = lastSkeletonRowRect?.height ?? rowHeightRef.current;

if (!tableRoot || !tableWrapper || !firstSkeletonRowRect || !lastSkeletonRowRect || !rowHeight) {
return;
}

rowHeightRef.current = rowHeight;
const nextRows = calculateAutoSkeletonRows({
maxRows,
minRows: minRowsValue,
rowHeight,

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

src/table/use-auto-skeleton-rows.ts:57

  • getOverflowHeight picks the first ancestor with overflow-y: auto|scroll, even if it isn't actually overflowing. In layouts where an ancestor has overflow-y: auto but expands with content, this returns 0 and prevents the overflow-correction step from removing rows even when the document (or another ancestor) is overflowing.
function getOverflowHeight(element: HTMLElement) {
  const scrollContainer = getScrollableParents(element)[0];
  if (scrollContainer) {
    return Math.max(0, scrollContainer.scrollHeight - scrollContainer.clientHeight);
  }

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.

3 participants