Table¶
Renders tabular data with column definitions, optional sorting, and row selection.
Usage¶
import { rgb, ui } from "@rezi-ui/core";
ui.table({
id: "users",
columns: [
{ key: "name", header: "Name", flex: 1, sortable: true, overflow: "middle" },
{ key: "role", header: "Role", width: 12 },
],
data: state.users,
getRowKey: (u) => u.id,
selection: state.selection,
selectionMode: "multi",
onSelectionChange: (keys) => app.update((s) => ({ ...s, selection: keys })),
stripeStyle: { odd: rgb(34, 37, 45) },
borderStyle: { variant: "double", color: rgb(120, 130, 145) },
})
Boilerplate-free: useTable¶
Use useTable(ctx, ...) inside composite widgets to auto-manage selection, sorting, and wiring:
import { defineWidget, ui, useTable } from "@rezi-ui/core";
const FilesTable = defineWidget<{ rows: readonly { id: string; name: string; size: number }[] }>(
(props, ctx) => {
const table = useTable(ctx, {
id: "files",
rows: props.rows,
columns: [
{ key: "name", header: "Name", flex: 1 },
{ key: "size", header: "Size", width: 10, align: "right" },
],
selectable: "multi",
sortable: true,
});
return ui.table(table.props);
},
);
useTable returns:
props: ready forui.table(...)selection,clearSelectionsortColumn,sortDirection,setSortrows: sorted rows currently rendered byprops
Props¶
| Prop | Type | Default | Description |
|---|---|---|---|
id |
string |
required | Unique identifier for focus and events |
columns |
TableColumn[] |
required | Column definitions (key, header, width/flex, sortability, renderers, overflow) |
data |
T[] |
required | Row data |
getRowKey |
(row: T, index: number) => string |
required | Stable key for each row |
rowHeight |
number |
1 |
Row height in cells. Use positive values for predictable keyboard and mouse navigation. |
headerHeight |
number |
1 |
Header row height in cells when showHeader is true. |
selection |
string[] |
[] |
Currently selected row keys |
selectionMode |
"none" \| "single" \| "multi" |
"none" |
Selection behavior |
onSelectionChange |
(keys: string[]) => void |
- | Called when selection changes |
sortColumn |
string |
- | Currently sorted column key |
sortDirection |
"asc" \| "desc" |
- | Current sort direction |
onSort |
(column: string, direction: "asc" \| "desc") => void |
- | Called when sort changes |
onRowPress |
(row: T, index: number) => void |
- | Row activation callback |
onRowDoublePress |
(row: T, index: number) => void |
- | Row double-activation callback (double-click) |
virtualized |
boolean |
true |
Enable windowed rendering for large datasets |
overscan |
number |
3 |
Extra rows rendered outside viewport |
showHeader |
boolean |
true |
Show/hide header row |
stripedRows |
boolean |
false |
Legacy stripe toggle (kept for compatibility) |
stripeStyle |
{ odd?, even? } |
- | Stripe background colors. Providing this enables stripes even when stripedRows is false. |
border |
"none" \| "single" |
"single" |
Legacy border toggle (kept for compatibility) |
borderStyle |
{ variant?, color? } |
- | Border glyph variant (single, double, rounded, heavy, dashed, heavy-dashed) and optional border color |
focusConfig |
FocusConfig |
- | Control focus visuals; { indicator: "none" } suppresses focused row highlight |
dsSize |
"sm" \| "md" \| "lg" |
"md" |
Design-system size preset for table recipe spacing |
dsTone |
"default" \| "primary" \| "danger" \| "success" \| "warning" |
"default" |
Design-system tone hook for recipe variants |
Design System Styling¶
Tables are design-system styled by default under the active ThemeDefinition.
tableRecipe() provides consistent colors for:
import { recipe } from "@rezi-ui/core";
// recipe.table(colors, { state: "header" | "row" | "selectedRow" | "focusedRow" | "stripe" })
This covers header, body rows, selected rows, focused rows, and stripe rows. See the Design System specification for details.
Examples¶
Sortable table¶
ui.table({
id: "files",
columns: [
{ key: "name", header: "Name", flex: 1, sortable: true },
{ key: "size", header: "Size", width: 10, align: "right", sortable: true },
],
data: files,
getRowKey: (f) => f.path,
sortColumn: state.sortColumn,
sortDirection: state.sortDirection,
onSort: (column, direction) => app.update((s) => ({ ...s, sortColumn: column, sortDirection: direction })),
})
Behavior¶
- Arrow keys navigate rows. Enter activates the selected row.
- Mouse click on a row selects it and moves focus to the table.
- In
selectionMode: "multi", Ctrl-click toggles the clicked row and Shift-click extends from the last clicked row. - Mouse click on a sortable header toggles sort and fires
onSort(column, direction). - When focused: Up from the first row focuses the header. Left/Right moves between columns. Enter toggles sort on the focused header.
- Double click on a row fires
onRowDoublePress(when provided). - Mouse scroll wheel scrolls rows when the table is virtualized.
Notes¶
- Tables can be virtualized; prefer virtualization for large datasets.
- Selection is tracked by row keys. Provide a stable
getRowKey. headerHeightis ignored whenshowHeaderisfalse.- Column
overflowdefaults to"ellipsis"and supports"clip"and"middle"per column. - Tables render a single-line frame by default. Set
border: "none"to suppress it, and useborderStyleto customize the active frame variant or color.
Related¶
- Virtual List - Windowed rendering for large linear datasets
- Tree - Hierarchical data navigation
- Input and Focus - Keyboard navigation behavior