Table
Composable React data table with header, body, footer, caption, sortable and filterable headers, selectable rows, sizes, striping, and a sticky header.
Build a Table from Header, Body, Row, Head, and Cell parts. Cell content is whatever you compose; headers gain sortable and filterable affordances, with the logic in your code.
When to use
Use Table for records with several attributes that users compare, sort, or select: applications, invoices, users. Keep the logic in your code and use the header affordances to expose it.
Use StructuredList for simple lists and DescriptionList for a single record.
Examples
Props
Props declared by Table. Native attributes of the underlying element pass through.
<Table>
| Prop | Type | Default | Description |
|---|---|---|---|
size | "sm" | "md" | "lg" | ||
striped | boolean | ||
contained | boolean | ||
stickyHeader | boolean | ||
aria-label | string | Accessible name for the scroll region wrapping the table. Strongly
recommended: a wide table scrolls horizontally, and a named, focusable
region lets keyboard and screen-reader users find and scroll it. When
provided, the wrapper becomes role="region" tabindex="0"; when omitted,
it degrades to a plain scroll container and a dev warning fires.
Note: this names the region, not the <table> - use <TableCaption> for
the table's own name. | |
aria-labelledby | string | Accessible name for the scroll region, by id reference. See aria-label. | |
maxHeight | string | number | Caps the scroll region's block-size (number → px) so the body scrolls
vertically within it. Required for stickyHeader to engage - sticky
needs a height-constrained, scrollable ancestor; without it the region
grows to content height and the header has nothing to stick to. |
<TableRow>
| Prop | Type | Default | Description |
|---|---|---|---|
selected | boolean | Visually highlights the row and sets data-state="selected". Selection
semantics for assistive tech come from a checkbox in the cell (see the
DataTable recipe), not from the row. |
<TableHead>
| Prop | Type | Default | Description |
|---|---|---|---|
align | "center" | "start" | "end" | ||
sortable | boolean | Renders the column as sortable: wraps content in a button and sets
aria-sort. Sort logic is the consumer's - wire onClick. | |
sortDirection | false | "desc" | "asc" | Current sort direction, or false when unsorted. | |
sortLabel | string | Visually-hidden, caller-localized cue appended to the sort button's
accessible name (e.g. "activate to sort ascending"). aria-sort already
conveys state, but a focused button otherwise announces only its column
label; this adds the action cue. Kept as a prop (not hard-coded text) so
the design system stays language-neutral - pass Arabic in RTL. Only used
when sortable. Typed string (not ReactNode) so interactive content
can't be hidden into a keyboard-reachable, invisible trap. | |
filterable | boolean | Renders the column's filter toggle: an icon-only funnel button sharing the
sort icon-box treatment, with aria-pressed. Filter logic is the
consumer's - wire onClick. Takes precedence over sortable. | |
filterActive | boolean | Whether the filter is currently applied - drives aria-pressed and the
active (filled) icon-box. | |
filterLabel | string | Visually-hidden, caller-localized name for the icon-only filter button
(e.g. "Filter"). Required with filterable so the toggle has an accessible
name; a dev warning fires when missing. | |
onClick | react.MouseEventHandler<HTMLButtonElement> | Click handler bound to the sort/filter button (only rendered when
sortable or filterable). | |
disabled | boolean | Disables the sort/filter button (renders the SDGA Disabled icon-box state). |
<TableCell>
| Prop | Type | Default | Description |
|---|---|---|---|
align | "center" | "start" | "end" |
Accessibility
Table renders a native <table>; add a TableCaption to name it. The scroll wrapper becomes a focusable role="region" when you pass aria-label, so keyboard users can scroll wide tables.
Sortable headers expose aria-sort, and the toggle buttons announce their state. Selectable rows use real checkboxes with labels.