Sortable table with sticky header, zebra rows, status pills, an empty state and optional pagination.
| Ava Thompson | Paid | $249.00 |
|---|---|---|
| Noah Garcia | Pending | $89.50 |
| Mia Chen | Paid | $1,240.00 |
npx shadcn@latest add https://hyperblur.dev/r/data-table.jsonWorks in any React project set up with the shadcn CLI. The file lands in components/hyperblur/data-table.tsx.
import { DataTable } from "@/components/hyperblur/data-table"
import { DataTable, pill } from "@/components/hyperblur/data-table";
<DataTable
columns={[
{ key: "customer", header: "Customer" },
{ key: "status", header: "Status", render: (row) => pill(String(row.status)) },
{ key: "amount", header: "Amount", align: "right" },
]}
rows={[{ customer: "Ava Thompson", status: "Paid", amount: 249 }]}
pageSize={5}
/>| Prop | Type | Default | Description |
|---|---|---|---|
| columns | { key: string; header: string; align?: "left" | "center" | "right"; render?: (row) => ReactNode; sortable?: boolean }[] | required | Column definitions. Sorting reads row[key]; render only changes how the cell looks. Columns are sortable unless sortable is false. |
| rows | Record<string, unknown>[] | required | Row objects. Click a header to sort ascending, again for descending, again to clear. |
| zebra | boolean | true | Alternate row shading. |
| maxHeight | number | 320 | Height in pixels at which the body scrolls under the sticky header. |
| emptyText | string | "No results" | Message shown when there are no rows. |
| pageSize | number | Rows per page. Omit to show everything and hide the pagination footer. | |
| caption | string | "Data table" | Accessible name for the table and its scroll region. |