Table
Native table with an optional interactive adapter.
- Browsers
- Chrome 123+Firefox 121+Safari 17.5+
- Tier
- 0
- Bundle compressed
- 617 B
- Forced layout budget
- 0 ms
- Axe budget
- 0
- SSR compatible
- Yes
- Published contract
- Test harness
Playground
Table
Native table example
| Name | Role | Status |
|---|---|---|
| Alice Chen | Admin | Active |
| Bob Smith | Editor | Active |
| Carol Lee | Viewer | Invited |
| 3 members · 2 active | ||
Sort, filter and expand
| Role | Details | ||
|---|---|---|---|
| Alice Chen | Admin | ||
| alice@example.com · Active | |||
| Bob Smith | Editor | ||
| bob@example.com · Active | |||
| Carol Lee | Viewer | ||
| carol@example.com · Invited | |||
| 3 members · 0 selected | |||
Sticky headers, footer and columns
API
Table.Root (native)
| Prop | Type | Default | Description |
|---|---|---|---|
layout | "auto" | "fixed" | "auto" | Native table layout. Selection, sorting and expansion use the explicit TableClient entry. |
size | "sm" | "md" | "lg" | — | Cell spacing from the selected stylesheet. |
variant | "solid" | "outline" | "ghost" | — | Surface variant from the selected stylesheet. |
render | ReactElement | ((props, state) => ReactElement) | — | Replace the rendered element while keeping behavior and accessibility wiring. |
Table.Footer
| Prop | Type | Default | Description |
|---|---|---|---|
sticky | boolean | — | Pins the footer to the block end of the scroll container. |
render | ReactElement | ((props, state) => ReactElement) | — | Replace the rendered element while keeping behavior and accessibility wiring. |
Table.RowHeader / Table.Cell / Table.ColumnHeader
| Prop | Type | Default | Description |
|---|---|---|---|
align | "start" | "center" | "end" | "start" | Logical text alignment for this cell. |
sticky | "start" | "end" | — | Pins a cell to the logical inline edge. For adjacent sticky cells set --uiify-table-sticky-offset on each cell. |
render | ReactElement | ((props, state) => ReactElement) | — | Replace the rendered element while keeping behavior and accessibility wiring. |
TableClient.ExpandTrigger / TableClient.ExpandedRow
| Prop | Type | Default | Description |
|---|---|---|---|
rowId* | string | — | Shared row key connecting the expansion button to its native <tr>. Put a <td colSpan={columnCount}> inside the expanded row. |
TableClient.Root — @gunkin/uiify/components/table/client
| Prop | Type | Default | Description |
|---|---|---|---|
aria-label | string | — | Accessible name for the table when no visible caption or heading names it. |
aria-labelledby | string | — | Id of the element that labels the table. |
selectionMode | "none" | "single" | "multiple" | "none" | Whether rows can be selected, and how many at a time; "none" renders a plain static table with no grid role. |
selectionBehavior | "toggle" | "replace" | — | Whether clicking a row adds it to the selection or replaces the current selection. |
defaultSelectedKeys | Iterable<string> | — | Row ids selected initially, leaving the selection uncontrolled inside the component. |
selectedKeys | Iterable<string> | — | Row ids selected right now, making the selection controlled by the caller. |
onSelectionChange | (selectedKeys: Set<string>) => void | — | Called with the new set of selected row ids whenever the selection changes. |
defaultSortDescriptor | SortDescriptor | null | — | Column and direction sorted initially, leaving the sort state uncontrolled inside the component. |
sortDescriptor | SortDescriptor | null | — | Column and direction sorted right now, making the sort controlled. |
onSortChange | (descriptor: SortDescriptor | null) => void | — | Called with the new sort descriptor, or null, when a sortable column header is activated. |
expandedKeys / defaultExpandedKeys | Iterable<string> | — | Controlled or initial expanded row keys. |
onExpandedChange | (keys: Set<string>) => void | — | Reports expansion requests. Controlled rows wait for the updated keys. |
render | ReactElement | ((props, state) => ReactElement) | — | Replace the rendered element while keeping behavior and accessibility wiring. |
Table.Header
| Prop | Type | Default | Description |
|---|---|---|---|
sticky | boolean | false | Pins this section to the scroll container; Header uses block start and Footer uses block end. |
render | ReactElement | ((props, state) => ReactElement) | — | Replace the rendered element while keeping behavior and accessibility wiring. |
Table.Body
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | The rows of the table body. |
render | ReactElement | ((props, state) => ReactElement) | — | Replace the rendered element while keeping behavior and accessibility wiring. |
Table.Row
| Prop | Type | Default | Description |
|---|---|---|---|
id* | string | — | Stable row id used as the selection key and as the element id. |
disabled | boolean | false | Prevents the row from being selected or focused by keyboard. |
selected | boolean | — | Marks the row selected in the server-rendered markup before the selection store takes over. |
render | ReactElement | ((props, state) => ReactElement) | — | Replace the rendered element while keeping behavior and accessibility wiring. |
Table.ColumnHeader
| Prop | Type | Default | Description |
|---|---|---|---|
id* | string | — | Column id that sort descriptors refer to. |
allowsSorting | boolean | false | Makes the header toggle sorting for its column and publish aria-sort. |
sortDirection | "ascending" | "descending" | null | — | Sort direction rendered for this column, used for the initial server markup when sorting is allowed. |
onClick | React.MouseEventHandler<HTMLTableCellElement> | — | Runs before sorting; preventDefault() vetoes the sort change. |
children | ReactNode | — | The header label. |
render | ReactElement | ((props, state) => ReactElement) | — | Replace the rendered element while keeping behavior and accessibility wiring. |
Table.Cell
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | The cell contents. |
render | ReactElement | ((props, state) => ReactElement) | — | Replace the rendered element while keeping behavior and accessibility wiring. |
Table.Caption
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | The caption text describing the table. |
render | ReactElement | ((props, state) => ReactElement) | — | Replace the rendered element while keeping behavior and accessibility wiring. |
Table.RowSelect
| Prop | Type | Default | Description |
|---|---|---|---|
rowId* | string | — | Id of the row this checkbox selects and deselects. |
Keyboard
| Key | Action |
|---|---|
| Tab | Focus sort, selection and expansion controls in TableClient |
| Enter / Space | Activate a focused sort or expansion button; toggle a checkbox |
| Arrow keys | Move between selectable body rows in TableClient |
Accessibility
The default Table renders native <table>, <caption>, <thead>, <tbody> and <tfoot> without client JavaScript; use ColumnHeader and RowHeader for header semantics. The /client entry adds sorting, selection, keyboard row navigation and controlled expansion, exposed through aria-sort, aria-expanded and aria-controls. ExpandedRow is a native <tr>; put a Cell with colSpan inside it. Filtering and ordering stay with the consumer.
Styling hooks
data-uiify-tabledata-partdata-layoutdata-sizedata-variantdata-stickydata-selecteddata-disabled--uiify-table-sticky-offset