feat(ui): add Table row selection support with visual states and documentation

- Add row state styling for hover, selected, pressed, and disabled states
- Fix checkbox rendering to only appear for multi-select toggle mode
- Add fixed 40px width for selection column header and cells
- Fix Column component to properly merge className prop
- Switch from React Aria headless Checkbox to styled Backstage UI Checkbox
- Add 12 selection Storybook stories covering all mode/behavior combinations
- Add interactive playground stories for selection mode and behavior
- Document row selection in docs-ui with examples

Signed-off-by: Johan Persson <johanopersson@gmail.com>
This commit is contained in:
Johan Persson
2025-11-27 11:20:59 +01:00
parent 61161c98fe
commit a20d317255
10 changed files with 662 additions and 23 deletions
+33 -2
View File
@@ -13,7 +13,9 @@ import {
tableHybridSnippet,
tableCellInteractionsSnippet,
tablePaginationSnippet,
tableSelectionSnippet,
tableSelectionActionsSnippet,
tableSelectionModeSnippet,
tableSelectionBehaviorSnippet,
tableSortingSnippet,
columnPropDefs,
rowPropDefs,
@@ -91,7 +93,36 @@ Coming soon.
### Row selection
Coming soon.
Tables support row selection with two configuration options: selection mode and selection behavior.
#### Selection mode
Use `selectionMode` to control how many rows can be selected. With `single`, only one row can be selected at a time. With `multiple`, any number of rows can be selected, and a header checkbox provides select-all functionality.
<Snippet
preview={<TableSnippet story="SelectionModePlayground" />}
code={tableSelectionModeSnippet}
/>
#### Selection behavior
Use `selectionBehavior` to control how selection is indicated and interacted with. With `toggle`, checkboxes appear for selection. With `replace`, selection is indicated by row background color—click to select, Cmd/Ctrl+click for multiple.
<Snippet
preview={<TableSnippet story="SelectionBehaviorPlayground" />}
code={tableSelectionBehaviorSnippet}
/>
#### With row actions
With toggle behavior, clicking a row triggers its action when nothing is selected. Once any row is selected, clicking toggles selection instead.
With replace behavior, clicking selects the row and double-clicking triggers the action.
<Snippet
preview={<TableSnippet story="SelectionToggleWithActions" />}
code={tableSelectionActionsSnippet}
/>
### Row Clicks
+49
View File
@@ -326,3 +326,52 @@ const { data: paginatedData, paginationProps } = useTable({
</TableBody>
</Table>
<TablePagination {...paginationProps} />`;
export const tableSelectionActionsSnippet = `import { Table, TableHeader, TableBody, Column, Row, Cell } from '@backstage/ui';
function MyTable() {
const [selectedKeys, setSelectedKeys] = React.useState(new Set([]));
return (
<Table
selectionMode="multiple"
selectionBehavior="toggle"
selectedKeys={selectedKeys}
onSelectionChange={setSelectedKeys}
onRowAction={(key) => console.log('Opening', key)}
>
<TableHeader>
<Column isRowHeader>Name</Column>
<Column>Status</Column>
</TableHeader>
<TableBody>
<Row id="1">
<Cell title="Component A" />
<Cell title="Active" />
</Row>
<Row id="2">
<Cell title="Component B" />
<Cell title="Inactive" />
</Row>
</TableBody>
</Table>
);
}`;
export const tableSelectionModeSnippet = `<Table
selectionMode="multiple" // or "single"
selectionBehavior="toggle"
selectedKeys={selectedKeys}
onSelectionChange={setSelectedKeys}
>
{/* ... */}
</Table>`;
export const tableSelectionBehaviorSnippet = `<Table
selectionMode="multiple"
selectionBehavior="toggle" // or "replace"
selectedKeys={selectedKeys}
onSelectionChange={setSelectedKeys}
>
{/* ... */}
</Table>`;