Table
Typed responsive table with captions, card or scroll layouts, stable row identity, sorting, controlled selection, loading, empty, and row actions.
Use Table for records compared across consistent fields. Add a caption. Choose cards for reordered narrow layouts or scroll to preserve columns. Controlled selection requires `rowKey` and localized selection labels.
Interactive example
Loading interactive example
Table
Table renders typed records with captions, sorting, controlled selection, responsive layouts, loading, empty, and row-action states.
Purpose
Use Table for records that users compare across consistent fields. Use a list when records do not share a comparison structure.
Anatomy
Columns define headers, alignment, sorting, and cell behavior. Rows supply typed data. Optional snippets render cells and row actions.
Add a caption that identifies the record set. Set captionVisuallyHidden when the surrounding page already shows the same title.
Use descriptive column labels and preserve the sort direction on sortable headers. Keep sorting state in the parent when a server owns the result order. When rows are reconstructed after sorting or fetching, pass rowKey={(row) => row.id} so cells retain their identity.
The default responsive="cards" layout stacks labelled values on narrow screens. Use responsive="scroll" when preserving the column comparison is more important than removing horizontal scrolling.
Controlled selection requires rowKey, a selectedKeys set, and onSelectedKeysChange. Supply localized selectAllLabel and selectRowLabel text. The select-all control reports a mixed state when only some available rows are selected. Disabled rows do not change through row or select-all controls.
Give each row action a label that includes the record name when nearby text does not provide it. Table does not paginate or virtualize records.
Tokens and style hooks
Table uses card, chrome, control, and selected layers with table geometry, text, border, radius, focus, and motion tokens. Cell snippets should use the same semantic variables.
API
| Member | Type | Kind | Required | Default |
|---|---|---|---|---|
caption | string | prop | No | undefined |
captionVisuallyHidden | boolean | prop | No | false |
cell | Snippet<[TableCellArgs<Row>]> | snippet | No | undefined |
columns | TableColumn[] | prop | Yes | |
empty | Snippet | snippet | No | undefined |
loading | boolean | prop | No | false |
loadingRows | number | prop | No | 5 |
onSortByChange | (sort: TableSort) => void | callback | No | undefined |
responsive | "cards" | "scroll" | prop | No | 'cards' |
rowAction | Snippet<[TableRowArgs<Row>]> | snippet | No | undefined |
rowKey | TableRowKey<Row> | prop | No | undefined |
rows | Row[] | prop | Yes | |
selection | TableSelection<Row> | undefined | prop | No | undefined |
sortBy | TableSort | binding | No | undefined |