Rows of records to scan, sort, search and select (also called a data table or data grid). Reach for it when people compare many records by the same fields; from a few rows to a million on a server.
import { useTable } from "@umriss-ui/table";
useTable takes the rows and hands back the Table and the Column that belong to them, so a column can only name a field the row has. The parts that touch no row, such as Toolbar or Search, are ordinary imports.
Every option of the hook and every prop of the table stands in the tables below; each feature has a page of its own in the sidebar.
Pass the rows to useTable and declare a Column per field; rowHeader names the row, and numbers align right and sort by value.
import { useTable } from "@umriss-ui/table";
interface Service {
id: string;
name: string;
team: string;
tier: number;
latencySlo: number;
}
const SERVICES: Service[] = [
{ id: "checkout", name: "Checkout", team: "Payments", tier: 1, latencySlo: 300 },
{ id: "sign-in", name: "Sign-in", team: "Identity", tier: 1, latencySlo: 200 },
{ id: "search", name: "Search", team: "Discovery", tier: 1, latencySlo: 250 },
{ id: "notifications", name: "Notifications", team: "Messaging", tier: 2, latencySlo: 800 },
];
export default function FirstTable() {
const { Table, Column } = useTable(SERVICES, { rowKey: (s) => s.id });
return (
<Table ariaLabel="Services">
<Column value="name" label="Service" rowHeader />
<Column value="team" label="Team" />
<Column value="tier" label="Tier" />
<Column value="latencySlo" label="Latency objective (ms)" />
</Table>
);
}
t.search and t.setSearch bind a field of the application's own, t.page and t.setPage a pager in the card's header. The table pages only while a Pagination stands in it; both pagers move the same page.
import { Button, Card, CardBody, CardHeader, Input, Stack, Text } from "@umriss-ui/core";
import { Pagination, useTable } from "@umriss-ui/table";
import type { TableRef } from "@umriss-ui/table";
interface Service {
id: string;
name: string;
team: string;
tier: number;
}
const SERVICES: Service[] = [
{ id: "checkout", name: "Checkout", team: "Payments", tier: 1 },
{ id: "billing", name: "Billing", team: "Payments", tier: 1 },
{ id: "refunds", name: "Refunds", team: "Payments", tier: 2 },
{ id: "sign-in", name: "Sign-in", team: "Identity", tier: 1 },
{ id: "accounts", name: "Accounts", team: "Identity", tier: 2 },
{ id: "search", name: "Search", team: "Discovery", tier: 1 },
{ id: "recommendations", name: "Recommendations", team: "Discovery", tier: 3 },
{ id: "catalogue", name: "Catalogue", team: "Discovery", tier: 2 },
{ id: "notifications", name: "Notifications", team: "Messaging", tier: 2 },
{ id: "webhooks", name: "Webhooks", team: "Messaging", tier: 3 },
{ id: "image-service", name: "Image service", team: "Platform", tier: 2 },
{ id: "reporting", name: "Reporting", team: "Platform", tier: 3 },
];
/* Written once for every table of the application, so it takes the table as
`of`, as the package's own parts do. It says which rows stand on the page,
out of how many: `rowCount` is what the search leaves, `rows` all there are.
A table that scrolls instead of paging has no page to step through. */
function RangePager({ of }: { of: TableRef }) {
if (of.virtual || of.rowCount === 0) return null;
const first = (of.page - 1) * of.pageSize + 1;
const last = Math.min(of.page * of.pageSize, of.rowCount);
return (
<Stack direction="row" gap={1} align="center">
<Text size="sm" tone="secondary">
{first}–{last} of {of.rowCount}
{of.rowCount < of.rows.length && ` (${of.rows.length} in all)`}
</Text>
<Button size="sm" aria-label="Previous page" disabled={of.page <= 1} onClick={() => of.setPage(of.page - 1)}>
‹
</Button>
<Button size="sm" aria-label="Next page" disabled={of.page >= of.pageCount} onClick={() => of.setPage(of.page + 1)}>
›
</Button>
</Stack>
);
}
export default function SearchAndPageFromAHeader() {
const t = useTable(SERVICES, { rowKey: (s) => s.id, pageSize: 5 });
const { Table, Column } = t;
const all = t.pageSize >= t.rows.length;
return (
<Card>
<CardHeader
divider
title="Services"
actions={
<Stack direction="row" gap={2} align="center" wrap>
<Input
type="search"
size="sm"
chars={18}
placeholder="Service or team"
aria-label="Search the services"
value={t.search}
onChange={(event) => t.setSearch(event.target.value)}
/>
<RangePager of={t} />
<Button size="sm" onClick={() => t.setPageSize(all ? 5 : t.rows.length)}>
{all ? "Five per page" : "Show all"}
</Button>
</Stack>
}
/>
<CardBody>
<Table ariaLabel="Services">
<Column value="name" label="Service" rowHeader />
<Column value="team" label="Team" />
<Column value="tier" label="Tier" />
<Pagination pageSizes={[5, 10]} />
</Table>
</CardBody>
</Card>
);
}
t.toggleSort, t.toggleColumn and t.setOrder change what the headers and the column menu change; t.sort, t.hidden and t.order say how it stands. t.asCsv() is the text an export writes.
import { useState } from "react";
import { Button, Checkbox, Select, Stack } from "@umriss-ui/core";
import { useTable } from "@umriss-ui/table";
import type { TableRef } from "@umriss-ui/table";
interface Service {
id: string;
name: string;
team: string;
tier: number;
latencySlo: number;
}
const SERVICES: Service[] = [
{ id: "checkout", name: "Checkout", team: "Payments", tier: 1, latencySlo: 300 },
{ id: "sign-in", name: "Sign-in", team: "Identity", tier: 1, latencySlo: 200 },
{ id: "search", name: "Search", team: "Discovery", tier: 1, latencySlo: 250 },
{ id: "notifications", name: "Notifications", team: "Messaging", tier: 2, latencySlo: 800 },
{ id: "reporting", name: "Reporting", team: "Platform", tier: 3, latencySlo: 2000 },
];
/** The columns the panel arranges, by id - the row header stays where it is. */
const COLUMNS = [
{ id: "team", label: "Team" },
{ id: "tier", label: "Tier" },
{ id: "latencySlo", label: "Latency objective (ms)" },
] as const;
/* Written once for every table of the application. In server mode the table
holds one page of the server's, and that is all `asCsv` can write - so the
button says so instead of pretending to copy the whole list. */
function CopyAsCsv({ of }: { of: TableRef }) {
const [copied, setCopied] = useState(false);
return (
<Button
size="sm"
onClick={() => {
void navigator.clipboard.writeText(of.asCsv()).then(() => setCopied(true));
}}
>
{copied ? "Copied" : of.server ? "Copy this page as CSV" : "Copy as CSV"}
</Button>
);
}
export default function SortArrangeAndExport() {
const t = useTable(SERVICES, { rowKey: (s) => s.id, defaultSort: { column: "tier", direction: "asc" } });
const { Table, Column } = t;
/* Empty until somebody arranges: then the natural order. */
const order = t.order.length > 0 ? t.order.filter((id) => COLUMNS.some((c) => c.id === id)) : COLUMNS.map((c) => c.id);
const sorted = t.sort[0];
const moveLeft = (id: string) => {
const at = order.indexOf(id);
t.setOrder(["name", ...order.slice(0, at - 1), id, order[at - 1]!, ...order.slice(at + 1)]);
};
return (
<Stack gap={3}>
<Stack direction="row" gap={2} align="center" wrap>
<Select size="sm" aria-label="Sort by" value={sorted?.column ?? ""} onChange={(event) => t.toggleSort(event.target.value)}>
<option value="name">Service</option>
{COLUMNS.map((c) => (
<option key={c.id} value={c.id}>
{c.label}
</option>
))}
</Select>
<Button size="sm" variant="ghost" onClick={() => sorted && t.toggleSort(sorted.column)}>
{sorted?.direction === "desc" ? "Descending" : "Ascending"}
</Button>
<CopyAsCsv of={t} />
</Stack>
<Stack direction="row" gap={3} align="center" wrap>
{order.map((id, i) => {
const label = COLUMNS.find((c) => c.id === id)!.label;
return (
<Stack key={id} direction="row" gap={1} align="center">
<Button size="sm" variant="ghost" aria-label={`Move ${label} to the left`} disabled={i === 0} onClick={() => moveLeft(id)}>
←
</Button>
<Checkbox label={label} checked={!t.hidden.includes(id)} onChange={() => t.toggleColumn(id)} />
</Stack>
);
})}
</Stack>
<Table ariaLabel="Services">
<Column value="name" label="Service" rowHeader />
<Column value="team" label="Team" />
<Column value="tier" label="Tier" />
<Column value="latencySlo" label="Latency objective (ms)" />
</Table>
</Stack>
);
}
Stat from @umriss-ui/core| Key | Action |
|---|---|
Enter / Space |
On a sortable header: sorts by the column, ascending; pressed again, descending. |
Escape |
Closes the tip that shows a cut value whole. |
A native table, named by ariaLabel: without it a screen reader announces a table with no name, so pass one, the more so where a page holds two. The rowHeader column's cells are row headers, so a reader names the row as it moves along it, and the row's checkbox, expander and actions are named after it too.
A sortable header holds a button, and its cell carries aria-sort, so the reader says which column orders the rows and in which direction. While loading is set the table is aria-busy.
A value cut short at the edge of its cell shows whole in a tip, under the pointer and on keyboard focus alike; the cell's text is the whole value all along, so a reader never meets the cut.
TableProps<Z>| Name | Type | Default | Description |
|---|---|---|---|
selectable | boolean | — | Adds the selection column. "All" means: the filtered set. Shown in: Name the row (Column), Pin columns to both sides (Width and pinning), Keep the header and the names in view (Width and pinning) and 14 more |
stickyHeader | boolean | — | Keeps the header row visible while scrolling. Shown in: Keep the header and the names in view (Width and pinning), Fold groups into a summary (Grouping), Group twenty thousand rows (Grouping) and 4 more |
stickyRowHeader | boolean | — | Keeps the row header column visible while scrolling sideways - the same as
pin="start" on the row header.Shown in: Keep the header and the names in view (Width and pinning), Stripes across a wide table (Row appearance), Show, hide and arrange (ColumnMenu) and 1 more |
striped | boolean | — | Discreet zebra stripes. |
density | "regular" | "compact" | the density of the UmrissProvider, else "regular" | How tightly the rows stand. Shown in: Fit long group names in a compact table (Grouping), Employees in the detail (Tree rows), Own staff and teams (Tree rows) and 4 more |
maxHeight | string | — | Height of the scroll area, e.g. "480px". A virtualised table needs it. Shown in: Keep the header and the names in view (Width and pinning), Fold groups into a summary (Grouping), Group twenty thousand rows (Grouping) and 4 more |
empty | ReactNode | — | What stands in the body when there are no rows. Empty because of a filter
the table shows itself – with the way back. Shown in: Restrict which rows a table has (Pre-filter), Show loading, empty, failed and no match (Row appearance) |
loading | boolean | — | Shows placeholder rows instead of the rows. Shown in: Rows from a request (Filter), Show loading, empty, failed and no match (Row appearance), Show loading, and drop a late answer (Server mode) and 1 more |
rowProps | (row: Z) => RowAttributes | — | Classes and data attributes per row. |
groupable | boolean | — | false: the user cannot group this table - the column menu offers no
grouping, and a grouping handed in is passed over.Shown in: Switch grouping off (Grouping) |
grid | boolean | — | Grid mode: the table is one tab stop, and the arrows walk its cells -
Home and End in the row, Ctrl+Home and Ctrl+End to the table's ends,
PageUp and PageDown by the rows in view. A cell's own controls are
reached with Enter or F2 and left with Escape; a column with edit is
edited in place. Without it the table stays a native table.Shown in: Work cell by cell (Grid mode), Combine grid mode with groups, pinning and many rows (Grid mode), Edit a comments column (Edits) and 6 more |
editMode | "cell" | "row" | — | Grid mode (ADR-0036): "cell" reports every cell as it is left
(onCellEdit); "row" opens every cell of a row that edits at once, as
one Row draft, and reports it only when the row is saved on purpose
(onRowSave) - by its Save button or Enter; Escape or Discard drops it.
A row with a draft is left only by saving or discarding it.Shown in: Save a row on purpose (Edits), Check a whole row before it is saved (Edits), Keep a list: add, change and delete rows (Edits) and 1 more |
newRow | () => Partial<Z> | — | What a new row starts with - the values the columns read before anything is typed. Without it, nothing. |
children | ReactNode | — | Columns, RowDetail, RowActions and the unbound parts.Shown in: Show a list of services, Search and page from a header of your own, Sort, arrange and export from controls of your own and 118 more |
| Name | Type | Default | Description |
|---|---|---|---|
onCellEdit | (edit: CellEdit<Z>) => void | — | Grid mode: an edit the user committed. The table applies nothing; the
cell shows the new value when the rows passed in carry it. Shown in: Combine grid mode with groups, pinning and many rows (Grid mode), Edit a comments column (Edits), Check an edit before it is reported (Edits) and 1 more |
onRowSave | (save: RowSave<Z>) => void | — | editMode="row": a saved Row draft, with the columns it changed.Shown in: Save a row on purpose (Edits), Check a whole row before it is saved (Edits), Keep a list: add, change and delete rows (Edits) and 1 more |
onRowAdd | (add: RowAdd) => void | — | Grid mode: puts up a "New row" button - in the table toolbar, or beneath the table without one. It opens an empty Row draft above the rows; saved, it is reported whole. The row appears when the rows passed in carry it. |
onRowDelete | (remove: RowDelete<Z>) => void | — | Grid mode: a Delete button on every row, which asks inside its row before
the delete is reported. The table removes nothing. Shown in: Keep a list: add, change and delete rows (Edits), Edit a dense table (Edits) |
| Name | Type | Default | Description |
|---|---|---|---|
ariaLabel | string | — | Accessible name of the table (not of the outer frame). Shown in: Show a list of services, Search and page from a header of your own, Sort, arrange and export from controls of your own and 118 more |
| Name | Type | Default | Description |
|---|---|---|---|
className | string | — | Classes on the outer frame of the table. Shown in: Pin columns to both sides (Width and pinning), Keep the header and the names in view (Width and pinning), Pin and size from controls of your own (Width and pinning) and 2 more |
TableOptions<Z>| Name | Type | Default | Description |
|---|---|---|---|
rowKeyrequired | (row: Z) => string | — | A stable key per row – the basis of selection and expansion. Shown in: Show a list of services, Search and page from a header of your own, Sort, arrange and export from controls of your own and 118 more |
pageSize | number | 10 | How many rows a page holds. Shown in: Search and page from a header of your own, Ask a question over several fields (Filter), Restrict which rows a table has (Pre-filter) and 7 more |
defaultSort | | SortLevel | null | The application's sort; it is the default that view leaves out.Shown in: Sort, arrange and export from controls of your own, A label wider than its column (Width and pinning), Sort by several columns (Sorting) and 10 more |
defaultGrouping | GroupingId<Z> | readonly GroupingId<Z>[] | ungrouped, until the user groups | The application's grouping: a column or group key, or up to three, the
outermost first. It is the default that view leaves out.Shown in: Group by one column (Grouping), Group on two levels (Grouping), Group on three levels (Grouping) and 23 more |
preFilter | (row: Z) => boolean | — | Which rows the table has at all – by permission, by tenant, by anything the user is not meant to undo. It is invisible: never a condition, never reset, never part of the view, and "43 of 1,204" counts only the rows it admits. It may stand in the call; a change leaves the page standing, and the model clamps it. |
rowFilters | readonly RowFilter<Z, any>[] | — | The row filters the table has: conditions the application defines over
the whole row and sets with t.setFilter(filter, condition) from a
control of its own. Named here so that a condition from initialView,
which arrives by id, is known in the first render.Shown in: Filter by a field no column shows (Filter), Rows from a request (Filter), Ask a question over several fields (Filter) and 3 more |
initialView | TableView | — | The view to start from, read once when the hook first runs; a different
value on a later render is ignored, as React ignores a changed
defaultValue. To go to a view later, call setView. The table
remembers none: where a view is kept is the application's decision.
Names no column carries fall out.Shown in: Ask a question over several fields (Filter), Fold groups into a summary (Grouping), Show loading, empty, failed and no match (Row appearance) and 2 more |
virtual | boolean | { overscan?: number } | — | Renders only what stands in the scroll area; paging is then off. Every
row is one row pitch tall, which the table measures itself (ADR-0042). Shown in: Group twenty thousand rows (Grouping), Scroll twenty thousand rows (Virtualisation), Measure two hundred thousand rows (Benchmark) and 1 more |
selection | TableSelection<string> | — | A selection from outside instead of its own – when the application holds it. Shown in: Hold the selection yourself (Selection) |
| Name | Type | Default | Description |
|---|---|---|---|
onViewChange | (view: TableView) => void | — | Every change the reader makes, once, always the whole view - the one to
keep, or to hand another table's setView. Not called for the view the
table starts with, nor for one setView applies.Shown in: Keep and restore a view (View) |
TableSnapshot<Z>| Name | Type | Default | Description |
|---|---|---|---|
rowsrequired | readonly Z[] | — | All the rows passed in, including those the pre-filter does not admit. |
filteredrequired | readonly Z[] | — | The filtered set: what the pre-filter admits and search and filters leave, across all pages. Shown in: Select rows (Selection), Scroll twenty thousand rows (Virtualisation) |
visiblerequired | readonly Z[] | — | What is rendered right now: the page or the window. |
pagerequired | number | — | The page shown, from 1. Without Pagination always 1. |
pageCountrequired | number | — | How many pages the filtered set makes. |
pageSizerequired | number | — | Rows per page. |
setPagerequired | (page: number) => void | — | Changes the page, clamped to those that exist. |
setPageSizerequired | (size: number) => void | — | Sets the rows per page; back to page one. |
searchrequired | string | — | The search text. |
setSearchrequired | (search: string) => void | — | Sets the search text; back to page one. |
sortrequired | readonly SortLevel[] | — | The sort levels, the first one first – only over columns that registered. Shown in: Sort, arrange and export from controls of your own |
toggleSortrequired | (column: string, additive?: boolean) => void | — | Sorts by a column. With additive a level is added instead of replacing the sort.Shown in: Sort, arrange and export from controls of your own |
toggleColumnrequired | (column: string) => void | — | Hides a column or shows it again. The row header stays. Shown in: Sort, arrange and export from controls of your own |
orderrequired | readonly string[] | — | The order of the columns as ids, as the user chose it. Shown in: Sort, arrange and export from controls of your own |
setOrderrequired | (order: readonly string[]) => void | — | Reorders the columns – on header, body and footer at once. Shown in: Sort, arrange and export from controls of your own |
pinnedrequired | Readonly<Record<string, Pin>> | — | The pinned columns by id - the declared ones until the user chooses. Shown in: Pin and size from controls of your own (Width and pinning) |
setPinrequired | (column: string, pin: Pin | null) => void | — | Pins a column to the start or the end, or unpins it with null.Shown in: Pin and size from controls of your own (Width and pinning) |
widthsrequired | Readonly<Record<string, number>> | — | The widths in pixels: those of the columns, and over them the dragged ones. Shown in: Pin and size from controls of your own (Width and pinning) |
setWidthrequired | (column: string, width: number | undefined) => void | — | Sets the width of a column; undefined takes it back.Shown in: Pin and size from controls of your own (Width and pinning) |
expandedrequired | readonly string[] | — | The keys of the expanded rows. |
toggleRowrequired | (key: string) => void | — | Expands a row or collapses it. |
filterrequired | Readonly<Record<string, unknown>> | — | The conditions of the column filters and row filters by id, in the order in which they were set. Whatever fits no column and no row filter is absent. |
setFilterrequired | SetFilter<Z> | — | Sets the condition of a column filter or a row filter; null clears it.
Back to page one. A condition that does not fit the kind of the filter – a
range on a list filter, a column without a filter, a row filter not in
rowFilters – is passed over with a warning in development.Shown in: Set a condition from outside the table (Filter), Filter by a field no column shows (Filter), Rows from a request (Filter) and 5 more |
conditionOfrequired | <B>(filter: RowFilter<Z, B>) => B | null | — | The condition of a row filter, as its type - null while it is lifted.Shown in: Filter by a field no column shows (Filter), Rows from a request (Filter), Ask a question over several fields (Filter) and 3 more |
selectionrequired | TableSelection<string> | — | The selection – its own or the one handed in through selection.Shown in: Select rows (Selection), Copy the selection (Export), Scroll twenty thousand rows (Virtualisation) and 3 more |
groupingrequired | readonly string[] | — | The ids the table is grouped by, the outermost first – only those a
groupable column or a group key carries, at most three. Shown in: Group and fold from controls of your own (Grouping) |
setGroupingrequired | (grouping: readonly string[]) => void | — | Groups by these columns or group keys; [] ungroups. Back to page one.Shown in: Group and fold from controls of your own (Grouping) |
setViewrequired | (view: TableView) => void | — | Goes to a whole view; what it leaves out goes back to where the table
starts, and names no column carries fall out. Not reported through onViewChange:
two tables kept in step by onViewChange: (v) => other.setView(v) in
both directions do not answer each other. A view with the content
already shown changes nothing.Shown in: Keep and restore a view (View) |
foldedrequired | readonly string[] | — | The paths of the folded groups that still occur. Shown in: Group and fold from controls of your own (Grouping) |
toggleFoldrequired | (path: string) => void | — | Folds a group or unfolds it. A group of one row does not fold. Shown in: Group and fold from controls of your own (Grouping) |
foldAllrequired | () => void | — | Folds every group that has more than one row. Shown in: Fold groups into a summary (Grouping) |
unfoldAllrequired | () => void | — | Unfolds every group. Shown in: Fold groups into a summary (Grouping) |
branchesrequired | readonly string[] | — | Tree rows: the keys of the open branches. Shown in: Open branches from controls of your own (Tree rows) |
toggleBranchrequired | (key: string) => void | — | Tree rows: opens a branch or closes it. Shown in: Open branches from controls of your own (Tree rows) |
unfoldAllBranchesrequired | () => void | — | Tree rows: opens every branch that has children. Shown in: Open branches from controls of your own (Tree rows) |
foldAllBranchesrequired | () => void | — | Tree rows: closes every branch. Shown in: Open branches from controls of your own (Tree rows) |
viewrequired | TableView | — | The part of the state an application can keep; whatever still stands as
the options set it up is absent. Shown in: Set a condition from outside the table (Filter), Fold groups into a summary (Grouping), Keep and restore a view (View) |
asCsvrequired | () => string | — | The filtered set in the visible columns as text for a spreadsheet - in
server mode the page. Shown in: Sort, arrange and export from controls of your own |
selectionAsTextrequired | () => string | — | The selected rows within the filtered set as tab-separated text under a
header line - the text Ctrl+C writes. "" with nothing selected.Shown in: Copy the selection (Export) |
virtualrequired | boolean | — | Whether it virtualises. |
rowCountrequired | number | — | How many rows the filtered set has - in server mode the server's count. |
serverrequired | boolean | — | Whether it is in server mode: the rows are one page of a server's. Shown in: Sort, arrange and export from controls of your own |
RowAttributesWhat a row carries in classes and data attributes.
type RowAttributes = { className?: string } & {
[data: `data-${string}`]: string | undefined;
};CellEdit<Z>An edit the user committed - reported, not applied.
| Name | Type | Default | Description |
|---|---|---|---|
rowKeyrequired | string | — | Shown in: Combine grid mode with groups, pinning and many rows (Grid mode), Edit a comments column (Edits), Check an edit before it is reported (Edits) and 1 more |
columnIdrequired | string | — | Shown in: Combine grid mode with groups, pinning and many rows (Grid mode), Check an edit before it is reported (Edits), Plan the team's capacity (Scenarios) |
valuerequired | unknown | — | The editor's value: text for "text", a number or null for
"number", a day or null for "date", an option for "select".Shown in: Combine grid mode with groups, pinning and many rows (Grid mode), Edit a comments column (Edits), Check an edit before it is reported (Edits) and 1 more |
rowrequired | Z | — | Shown in: Check an edit before it is reported (Edits), Plan the team's capacity (Scenarios) |
RowSave<Z>A Row draft the user saved (ADR-0036) - reported, not applied.
| Name | Type | Default | Description |
|---|---|---|---|
rowKeyrequired | string | — | Shown in: Save a row on purpose (Edits), Check a whole row before it is saved (Edits), Keep a list: add, change and delete rows (Edits) and 1 more |
changesrequired | Readonly<Record<string, unknown>> | — | The columns the draft changed, by column id, with their editors' values. Shown in: Save a row on purpose (Edits), Check a whole row before it is saved (Edits), Keep a list: add, change and delete rows (Edits) and 1 more |
rowrequired | Z | — | Shown in: Save a row on purpose (Edits) |
RowAddA new row the user saved: every column that edits, by column id.
| Name | Type | Default | Description |
|---|---|---|---|
valuesrequired | Readonly<Record<string, unknown>> | — |
RowDelete<Z>A row the user asked to delete, and confirmed.
| Name | Type | Default | Description |
|---|---|---|---|
rowKeyrequired | string | — | Shown in: Keep a list: add, change and delete rows (Edits), Edit a dense table (Edits) |
rowrequired | Z | — |
SortLevel<K extends string = string>One level of the sort. Several levels act in their order: the second decides only what the first leaves open.
| Name | Type | Default | Description |
|---|---|---|---|
columnrequired | K | — | Shown in: Sort, arrange and export from controls of your own, A label wider than its column (Width and pinning), Sort by several columns (Sorting) and 10 more |
directionrequired | SortDirection"asc" | "desc" | — | Shown in: Sort, arrange and export from controls of your own, A label wider than its column (Width and pinning), Sort by several columns (Sorting) and 10 more |
GroupingId<Z>A column or group key the table can be grouped by. The columns stand in the JSX, which the hook does not see: a field name is suggested, any id is taken, and one that nothing carries falls out.
type GroupingId<Z> = Field<Z> | (string & {});TableView<K extends string = string>Search, conditions, sort levels, page, page size, hidden columns, order, dragged widths, the grouping and the pinned columns. Whatever is at its default is absent. The pre-filter never belongs to it: it is a function of the application.
| Name | Type | Default | Description |
|---|---|---|---|
search | string | — | Shown in: Show loading, empty, failed and no match (Row appearance), Hand the table one page (Server mode), Sort and search on the server (Server mode) and 3 more |
conditions | Readonly<Record<string, unknown>> | — | The conditions of the column filters, per column. A condition for a column
that does not exist, or whose filter is of another kind, falls out. Shown in: Ask a question over several fields (Filter), A dispatcher's bar (Toolbar controls), Hand the table one page (Server mode) and 4 more |
sort | readonly SortLevel<K>[] | — | Shown in: Keep and restore a view (View), Hand the table one page (Server mode), Sort and search on the server (Server mode) and 3 more |
page | number | — | Shown in: Hand the table one page (Server mode), Sort and search on the server (Server mode), Name the values a list filter offers (Server mode) and 2 more |
pageSize | number | — | Shown in: Hand the table one page (Server mode), Sort and search on the server (Server mode), Name the values a list filter offers (Server mode) and 2 more |
order | readonly K[] | — | |
widths | Readonly<Record<string, number>> | — | Column widths the user has dragged, in pixels. |
grouping | readonly K[] | — | The columns and group keys the table is grouped by, the outermost first. |
folded | readonly string[] | — | The paths of the folded groups. A path that no longer occurs falls out. Shown in: Fold groups into a summary (Grouping) |
branches | readonly string[] | — | Tree rows: the keys of the open branches. A key that no longer occurs falls out. |
pinned | Readonly<Record<string, Pin>> | — | The pinned columns, whole, once the user's choice deviates from what the
columns declare - {} when every declared pin was undone. A column that
does not exist falls out. |
TableSelection<T extends string | number>What useTableSelection returns: the selected keys and the gestures on
them. Give it to useTable as selection when the application holds the
selection.
| Name | Type | Default | Description |
|---|---|---|---|
selectedrequired | ReadonlySet<T> | — | The keys currently selected. Shown in: Work through the alerts (Scenarios) |
isSelectedrequired | (id: T) => boolean | — | Shown in: Select rows (Selection), Hold the selection yourself (Selection) |
togglerequired | (id: T) => void | — | Shown in: Hold the selection yourself (Selection) |
toggleAllrequired | () => void | — | Selects all the keys passed in - or, when all of them are selected already, deselects them. Keys outside them stay as they are. |
clearrequired | () => void | — | Shown in: Hold the selection yourself (Selection), Work through the alerts (Scenarios), Find a late shipment (Scenarios) |
allSelectedrequired | boolean | — | true when every key passed in is selected. |
someSelectedrequired | boolean | — | true when some - but not all - are selected. |
countrequired | number | — | Shown in: Select rows (Selection), Hold the selection yourself (Selection), Copy the selection (Export) and 2 more |
PinWhere a pinned column stands: in the block before or after the others.
type Pin = "start" | "end";SetFilter<Z>Sets a condition from outside. Typed at the field of the row, not at the
column: the columns stand in the JSX, and the hook does not see that
(ADR-0017). An id that is not a field name – a computed column or an id of
one's own – takes any condition; through it the condition of a filter of
one's own is set as well.
interface SetFilter<Z> {
<B>(filter: RowFilter<Z, B>, condition: B | null): void;
<K extends Field<Z>>(column: K, condition: FieldCondition<Z[K]> | null): void;
<I extends string>(column: I & (I extends Field<Z> ? never : unknown), condition: unknown): void;
}SortDirectionThe direction of one sort level: asc puts the smallest value on top,
desc the largest.
type SortDirection = "asc" | "desc";Field<Z>The field names of a row.
type Field<Z> = Extract<keyof Z, string>;FieldCondition<W>What can be set as a condition on a field: a list of its values, and for numbers and points in time a range as well.
type FieldCondition<W> =
| ListCondition<W>
| ([Present<W>] extends [number] ? RangeCondition<number> : [Present<W>] extends [Date] ? RangeCondition<Date> : never);ListCondition<W>The condition of a list filter: the chosen values, an absent one as null.
type ListCondition<W> = readonly (Present<W> | null)[];Present<W>The value without the absence - that is what children gets.
type Present<W> = Exclude<W, Absent>;RangeCondition<W>The condition of a range filter: both bounds inclusive, each may be absent.
AbsentA value that is not there: null or undefined.
type Absent = null | undefined;What umriss deliberately does not build, and why: ADR-0032.