Merge pull request #33379 from backstage/rugvip/document-table-cell-requirement
ui: document table cell wrapper requirement
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/ui': patch
|
||||
---
|
||||
|
||||
Added documentation for the table cell wrapper requirement to TSDoc comments for `Cell`, `CellText`, `CellProfile`, `ColumnConfig`, and `RowRenderFn`.
|
||||
@@ -42,6 +42,7 @@ import {
|
||||
tableCombinedSnippet,
|
||||
tableCustomRowSnippet,
|
||||
tablePrimitivesSnippet,
|
||||
tableCellRequirementSnippet,
|
||||
} from './snippets';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
@@ -94,6 +95,18 @@ For full control over state, use the controlled props instead:
|
||||
- `search` / `onSearchChange`
|
||||
- `filter` / `onFilterChange`
|
||||
|
||||
### Cell Requirement
|
||||
|
||||
Every cell rendered via `ColumnConfig.cell` (or inside a custom `RowRenderFn`) **must** return a cell component as the top-level element. The available cell components are:
|
||||
|
||||
- **`CellText`** — displays a title with optional description and icon.
|
||||
- **`CellProfile`** — displays an avatar with a name and optional description.
|
||||
- **`Cell`** — a generic wrapper for fully custom cell content.
|
||||
|
||||
Returning bare text, React fragments, or other elements without wrapping them in one of these cell components will break the table layout.
|
||||
|
||||
<CodeBlock code={tableCellRequirementSnippet} />
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Sorting
|
||||
|
||||
@@ -57,6 +57,23 @@ const {
|
||||
filter, // { value, onChange } for filters
|
||||
} = useTable({ ... });`;
|
||||
|
||||
// =============================================================================
|
||||
// Cell Requirement
|
||||
// =============================================================================
|
||||
|
||||
export const tableCellRequirementSnippet = `// ✅ Correct — CellText is the top-level element
|
||||
cell: item => <CellText title={item.name} />;
|
||||
|
||||
// ✅ Correct — Cell wraps custom content
|
||||
cell: item => (
|
||||
<Cell>
|
||||
<MyCustomContent value={item.name} />
|
||||
</Cell>
|
||||
);
|
||||
|
||||
// ❌ Wrong — bare text without a cell wrapper
|
||||
cell: item => <span>{item.name}</span>;`;
|
||||
|
||||
// =============================================================================
|
||||
// Common Patterns
|
||||
// =============================================================================
|
||||
|
||||
@@ -766,7 +766,7 @@ export const Cell: {
|
||||
displayName: string;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export type CellOwnProps = {
|
||||
className?: string;
|
||||
};
|
||||
@@ -774,7 +774,7 @@ export type CellOwnProps = {
|
||||
// @public (undocumented)
|
||||
export const CellProfile: (props: CellProfileProps) => JSX_2.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export type CellProfileOwnProps = {
|
||||
src?: string;
|
||||
name?: string;
|
||||
@@ -784,12 +784,12 @@ export type CellProfileOwnProps = {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export interface CellProfileProps
|
||||
extends CellProfileOwnProps,
|
||||
Omit<CellProps_2, keyof CellProfileOwnProps> {}
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export interface CellProps
|
||||
extends CellOwnProps,
|
||||
Omit<CellProps_2, keyof CellOwnProps> {}
|
||||
@@ -800,7 +800,7 @@ export const CellText: {
|
||||
displayName: string;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export type CellTextOwnProps = {
|
||||
title: string;
|
||||
description?: string;
|
||||
@@ -810,7 +810,7 @@ export type CellTextOwnProps = {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export interface CellTextProps
|
||||
extends CellTextOwnProps,
|
||||
Omit<CellProps_2, keyof CellTextOwnProps> {}
|
||||
@@ -849,9 +849,8 @@ export interface CheckboxProps
|
||||
// @public (undocumented)
|
||||
export const Column: (props: ColumnProps) => JSX_2.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export interface ColumnConfig<T extends TableItem> {
|
||||
// (undocumented)
|
||||
cell: (item: T) => ReactElement;
|
||||
// (undocumented)
|
||||
defaultWidth?: ColumnSize | null;
|
||||
@@ -2068,7 +2067,7 @@ export interface RowProps<T>
|
||||
extends RowOwnProps<T>,
|
||||
Omit<RowProps_2<T>, keyof RowOwnProps> {}
|
||||
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export type RowRenderFn<T extends TableItem> = (params: {
|
||||
item: T;
|
||||
index: number;
|
||||
|
||||
@@ -93,17 +93,35 @@ export interface ColumnProps
|
||||
extends ColumnOwnProps,
|
||||
Omit<ReactAriaColumnProps, keyof ColumnOwnProps> {}
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Own props for the {@link Cell} component.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type CellOwnProps = {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Props for the {@link Cell} component.
|
||||
*
|
||||
* `Cell` is a generic cell wrapper for custom cell content. When rendering
|
||||
* cells via {@link ColumnConfig.cell} or a custom {@link RowRenderFn}, the
|
||||
* returned element **must** be a cell component (`Cell`, `CellText`, or
|
||||
* `CellProfile`) at the top level. Returning bare text or other elements
|
||||
* without a cell wrapper will break the table layout.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface CellProps
|
||||
extends CellOwnProps,
|
||||
Omit<ReactAriaCellProps, keyof CellOwnProps> {}
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Own props for the {@link CellText} component.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type CellTextOwnProps = {
|
||||
title: string;
|
||||
description?: string;
|
||||
@@ -113,12 +131,25 @@ export type CellTextOwnProps = {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Props for the {@link CellText} component.
|
||||
*
|
||||
* `CellText` renders a table cell with a title and optional description. It
|
||||
* is one of the cell components (`Cell`, `CellText`, `CellProfile`) that
|
||||
* **must** be used as the top-level element returned from
|
||||
* {@link ColumnConfig.cell} or a custom {@link RowRenderFn}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface CellTextProps
|
||||
extends CellTextOwnProps,
|
||||
Omit<ReactAriaCellProps, keyof CellTextOwnProps> {}
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Own props for the {@link CellProfile} component.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type CellProfileOwnProps = {
|
||||
src?: string;
|
||||
name?: string;
|
||||
@@ -128,7 +159,16 @@ export type CellProfileOwnProps = {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Props for the {@link CellProfile} component.
|
||||
*
|
||||
* `CellProfile` renders a table cell with an avatar, name, and optional
|
||||
* description. It is one of the cell components (`Cell`, `CellText`,
|
||||
* `CellProfile`) that **must** be used as the top-level element returned
|
||||
* from {@link ColumnConfig.cell} or a custom {@link RowRenderFn}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface CellProfileProps
|
||||
extends CellProfileOwnProps,
|
||||
Omit<ReactAriaCellProps, keyof CellProfileOwnProps> {}
|
||||
@@ -151,10 +191,27 @@ export interface PagePagination extends TablePaginationProps {
|
||||
/** @public */
|
||||
export type TablePaginationType = NoPagination | PagePagination;
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Configuration for a single table column.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface ColumnConfig<T extends TableItem> {
|
||||
id: string;
|
||||
label: string;
|
||||
/**
|
||||
* Renders the cell content for this column.
|
||||
*
|
||||
* **Important:** The returned element **must** be a cell component at the
|
||||
* top level — either `Cell`, `CellText`, or `CellProfile`. Returning bare
|
||||
* text, fragments, or other elements without a cell wrapper will break the
|
||||
* table layout.
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
* cell: item => <CellText title={item.name} />
|
||||
* ```
|
||||
*/
|
||||
cell: (item: T) => ReactElement;
|
||||
header?: () => ReactElement;
|
||||
isSortable?: boolean;
|
||||
@@ -173,7 +230,16 @@ export interface RowConfig<T extends TableItem> {
|
||||
getIsDisabled?: (item: T) => boolean;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Custom render function for table rows.
|
||||
*
|
||||
* When using a custom row render function, each cell rendered inside the row
|
||||
* **must** use a cell component (`Cell`, `CellText`, or `CellProfile`) as
|
||||
* the top-level element. Returning bare text or other elements without a
|
||||
* cell wrapper will break the table layout.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type RowRenderFn<T extends TableItem> = (params: {
|
||||
item: T;
|
||||
index: number;
|
||||
|
||||
Reference in New Issue
Block a user