feat(ui): export TableBodySkeleton as public API (#33731)

* feat(ui): export TableBodySkeleton as public API

Export the TableBodySkeleton component so it can be used independently
of the built-in Table component. Relax the column type constraint from
ColumnConfig<T> to { id: string } for compatibility with custom column
types.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Jonathan Roebuck <jroebuck@spotify.com>

* fix(ui): use direct index instead of parsing skeleton item ID

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Jonathan Roebuck <jroebuck@spotify.com>

* Update .changeset/export-table-body-skeleton.md

Co-authored-by: Johan Persson <johanopersson@gmail.com>
Signed-off-by: Jonathan Roebuck <jroebuck@spotify.com>

* docs(ui): add TableBodySkeleton to table primitives documentation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Jonathan Roebuck <jroebuck@spotify.com>

---------

Signed-off-by: Jonathan Roebuck <jroebuck@spotify.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Johan Persson <johanopersson@gmail.com>
This commit is contained in:
Jonathan Roebuck
2026-04-08 10:21:17 +01:00
committed by GitHub
parent 1e97694b15
commit f73876a472
6 changed files with 43 additions and 5 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/ui': patch
---
Exported the `TableBodySkeleton` component as a public API for use outside of the built-in `Table` component. The component now accepts any column array whose items have an `id` property, making it compatible with custom column types.
@@ -24,6 +24,7 @@ import {
tableRootPropDefs,
columnPropDefs,
rowPropDefs,
tableBodySkeletonPropDefs,
} from './props-definition';
import {
tableUsageSnippet,
@@ -303,6 +304,12 @@ Low-level components for building custom table layouts.
<ReactAriaLink component="Cell" href={reactAriaUrls.cell} />
#### TableBodySkeleton
A table body that renders animated skeleton rows as a loading placeholder. Useful when composing with primitives and you need a loading state without the full `Table` component.
<PropsTable data={tableBodySkeletonPropDefs} />
<Theming definition={TableDefinition} />
<ChangelogComponent
@@ -317,5 +324,6 @@ Low-level components for building custom table layouts.
'cell',
'cell-text',
'cell-profile',
'table-body-skeleton',
]}
/>
@@ -491,6 +491,15 @@ export const columnPropDefs: Record<string, PropDef> = {
},
};
export const tableBodySkeletonPropDefs: Record<string, PropDef> = {
columns: {
type: 'enum',
values: ['{ id: string }[]'],
description:
'Array of column objects. Each item must have an `id` property. Compatible with `ColumnConfig` and custom column types.',
},
};
export const rowPropDefs: Record<string, PropDef> = {
id: {
type: 'enum',
+7
View File
@@ -2700,6 +2700,13 @@ export interface TableBodyProps<T extends object>
extends TableBodyOwnProps,
Omit<TableBodyProps_2<T>, keyof TableBodyOwnProps> {}
// @public
export function TableBodySkeleton<
T extends {
id: string;
},
>(input: { columns: readonly T[] }): JSX_2.Element;
// @public
export const TableDefinition: {
readonly styles: {
@@ -18,25 +18,33 @@ import { TableBody } from './TableBody';
import { Row } from './Row';
import { Cell } from './Cell';
import { Skeleton } from '../../Skeleton';
import type { ColumnConfig, TableItem } from '../types';
const SKELETON_ROW_COUNT = 5;
const SKELETON_WIDTHS = ['75%', '50%', '60%', '45%', '70%'];
const skeletonItems = Array.from({ length: SKELETON_ROW_COUNT }, (_, i) => ({
id: `skeleton-${i}`,
index: i,
}));
/** @internal */
export function TableBodySkeleton<T extends TableItem>({
/**
* A table body that renders animated skeleton rows as a loading placeholder.
*
* @remarks
* Accepts any column array whose items have an `id` property, making it
* compatible with both `ColumnConfig` and custom column types.
*
* @public
*/
export function TableBodySkeleton<T extends { id: string }>({
columns,
}: {
columns: readonly ColumnConfig<T>[];
columns: readonly T[];
}) {
return (
<TableBody items={skeletonItems} dependencies={[columns]}>
{item => {
const rowIndex = Number(item.id.split('-')[1]);
const rowIndex = item.index;
return (
<Row id={item.id} columns={columns}>
{column => (
@@ -23,6 +23,7 @@ export { Row } from './components/Row';
export { Cell } from './components/Cell';
export { CellText } from './components/CellText';
export { CellProfile } from './components/CellProfile';
export { TableBodySkeleton } from './components/TableBodySkeleton';
export { useTable } from './hooks/useTable';
export type {