Xzero UI
Pro library

Sortable data table

Compare structured records with sortable columns.

$ pnpm dlx shadcn@4.23.0 add @xzero-ui/sortable-data-table
Live · keyboard ready

When to use

When not to use

Installation

Register both Xzero UI namespaces in your project's components.json:

{
  "registries": {
    "@xzero-ui": "https://mcp.xzero.co.uk/r/{name}.json",
    "@xzero-ui-pro": "https://mcp.xzero.co.uk/r/pro/{name}.json"
  }
}
npx shadcn@4.23.0 add @xzero-ui/sortable-data-table

Install xzero-foundation once, and import @/components/xzero/foundation.css in your app root. No Xzero token is used by this snapshot. For sample portraits, photos, fonts, or logos, download https://mcp.xzero.co.uk/install-assets.mjs and run node xzero-install-assets.mjs <receiving-project>.

Usage

import { SortableDataTable } from "@/components/xzero/sortable-data-table/sortable-data-table";

const projects = [
  { id: "p1", name: "Harbour", owner: "Maya", budget: 42000 },
  { id: "p2", name: "Atlas", owner: "Leo", budget: 18500 },
];

export function Projects() {
  return (
    <SortableDataTable
      rows={projects}
      rowKey="id"
      caption="Projects"
      columns={[{ key: "name", label: "Name" }, { key: "owner", label: "Owner" }, { key: "budget", label: "Budget" }]}
      defaultSort={{ key: "name", direction: "asc" }}
      selectable
      itemName={{ one: "project", other: "projects" }}
    />
  );
}

API reference

SortableDataTable

A generic table with sortable columns, optional row selection, and rows that glide when re-sorted.

PropTypeDefaultDescription
rows (required)T[]–Row objects.
columns (required){ key: string; label: string; sortable?: boolean; render?: (value: unknown, row: T) => ReactNode; numeric?: boolean; width?: number | string }[]–Column definitions. Columns are sortable unless sortable is false; numeric is detected when every value is a number.
rowKey (required)keyof T | ((row: T) => string)–Stable key per row.
captionstring"Data table"Table caption, used as its accessible name.
emptyMessagestring"No rows to show"Shown when rows is empty.
defaultSort{ key: string; direction: "asc" | "desc" }–Sort applied on first render.
onSortChange(sort: SortState) => void–Called when a header is pressed.
selectablebooleanfalseAdds a checkbox column, row click selection, and a count line with Clear.
selectedKeysstring[]–Controlled selection.
defaultSelectedKeysstring[]–Initial selection when uncontrolled.
onSelectionChange(keys: string[]) => void–Called with the new selection.
itemName{ one: string; other: string }{ one: "row", other: "rows" }Noun for the count line, as in "6 projects".

Keyboard interactions

KeysAction
ArrowLeft / ArrowRightMoves between sortable headers.
ArrowUp / ArrowDownMoves between row checkboxes; down from Select all enters the rows.
Home / EndJumps to the first or last header or row checkbox.
Enter / SpaceSorts by a header or toggles a checkbox.
Shift + clickSelects a range of rows.
EscapeClears the selection.

Accessibility

Motion

Responsive behavior

Performance

Notes for AI

Also in tables

Guidance for AI tools

Sortable data table: Compare structured records with sortable columns. Follow the declared prop types and do not invent props. Keep keyboard access, reduced motion support, and both light and dark themes intact when adapting it.

Full library index: https://ui.xzero.co.uk/llms.txt

Browse all components