Data Table
Table plus the behaviour layered on top: a TextField filters rows, sortable columns are real <button>s in the header, and Pagination splits the result into pages, all composed from existing primitives, not a new grid widget. Filter, sort, and page state live inside the component, so you hand it columns and data and it does the rest.
17 results
| Status | ||
|---|---|---|
| Ada Okoye | Engineering | Active |
| Bram Visser | Design | Away |
| Celia Nakamura | Engineering | Active |
| Dario Conti | Product | Offline |
| Elin Berg | Engineering | Active |
Usage
import { DataTable } from "@kernelui/react";
import type { DataTableColumn } from "@kernelui/react";
interface TeamMember {
name: string;
role: string;
}
const members: TeamMember[] = [
{ name: "Ada Okoye", role: "Engineering" },
{ name: "Bram Visser", role: "Design" },
];
const columns: DataTableColumn<TeamMember>[] = [
{ key: "name", header: "Name", render: (row) => row.name, sortable: true },
{ key: "role", header: "Role", render: (row) => row.role, sortable: true },
];
function TeamTable() {
return <DataTable columns={columns} data={members} rowKey={(row) => row.name} />;
}Props
| Prop | Type | Default |
|---|---|---|
columns | DataTableColumn<T>[] (required) | — |
data | T[] (required) | — |
rowKey | (row: T) => string (required) | — |
filterPlaceholder | string | "Filter" |
pageSize | number | 10 |
caption | ReactNode | — |
Column shape
| Field | Type | Default |
|---|---|---|
key | string (required) | — |
header | string (required) | — |
render | (row: T) => ReactNode (required) | — |
sortable | boolean | false |
sortValue | (row: T) => string | number | falls back to render's text |
Accessibility
- Sortable headers set
aria-sort="ascending" | "descending" | "none"directly on the<th>, the standard way to expose sort state, rather than a custom visual-only indicator. - The sort control inside each sortable header is a real, focusable
<button>, keyboard-activatable with Enter or Space, not a clickable<div>. - A
role="status"live region reports the filtered result count, so assistive tech hears "3 results" when the filter narrows the table, without needing to re-read the whole table. - Pagination reuses
Pagination's own<nav aria-label="Pagination">andaria-current="page"wiring unchanged.