$ rezi
Widgets

Table

Renders tabular data with column definitions, optional sorting, and row selection.

Renders tabular data with column definitions, optional sorting, and row selection.

Usage

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: { r: 34, g: 37, b: 45 } },
  borderStyle: { variant: "double", color: { r: 120, g: 130, b: 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 for ui.table(...)
  • selection, clearSelection
  • sortColumn, sortDirection, setSort
  • rows: sorted rows currently rendered by props

Props

PropTypeDefaultDescription
idstringrequiredUnique identifier for focus and events
columnsTableColumn[]requiredColumn definitions (key, header, width/flex, sortability, renderers, overflow)
dataT[]requiredRow data
getRowKey(row: T, index: number) => stringrequiredStable key for each row
rowHeightnumber1Row height in cells. Use positive values for predictable keyboard and mouse navigation.
headerHeightnumber1Header row height in cells when showHeader is true.
selectionstring[][]Currently selected row keys
selectionMode"none" | "single" | "multi""none"Selection behavior
onSelectionChange(keys: string[]) => void-Called when selection changes
sortColumnstring-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)
virtualizedbooleantrueEnable windowed rendering for large datasets
overscannumber3Extra rows rendered outside viewport
showHeaderbooleantrueShow/hide header row
stripedRowsbooleanfalseLegacy stripe toggle (kept for compatibility)
stripeStyle{ odd?, even? }-Stripe background colors. Providing this enables stripes even when stripedRows is false.
border"none" | "single""none"Legacy border toggle (kept for compatibility)
borderStyle{ variant?, color? }-Border glyph variant (single, double, rounded, heavy, dashed, heavy-dashed) and optional border color

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.
  • 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.
  • headerHeight is ignored when showHeader is false.
  • Column overflow defaults to "ellipsis" and supports "clip" and "middle" per column.
  • borderStyle is applied only when border !== "none" to preserve legacy behavior.

On this page