A full-featured table built on TanStack Table v9: search, faceted filters, sorting, column visibility, row selection, pagination and CSV or Excel export.
$ pnpm dlx shadcn@latest add https://dashral.com/r/data-table.jsonInstallation
$ pnpm dlx shadcn@latest add https://dashral.com/r/data-table.jsonAdds the component, the components it builds on, its npm packages and the theme tokens it uses. Using Dashral often? Add the registry to components.json once:
{
"registries": {
"@dashral": "https://dashral.com/r/{name}.json"
}
}Then add components by name:
$ pnpm dlx shadcn@latest add @dashral/data-tableUsage
import { createDataTableColumnHelper, DataTable } from "@/components/dashral/data-table"
type Customer = { name: string; email: string; plan: string }
const helper = createDataTableColumnHelper<Customer>()
const columns = helper.columns([
helper.accessor("name", { header: "Name" }),
helper.accessor("email", { header: "Email" }),
helper.accessor("plan", { header: "Plan" }),
])
<DataTable columns={columns} data={customers} getRowId={(row) => row.email} exportable />Examples
Filters, selection, actions and export
Faceted filters need filterFn: "oneOf" on the column. The toolbar prop receives the table for bulk actions. exportable adds a CSV and Excel menu.
| Product | Status | ||||||
|---|---|---|---|---|---|---|---|
| INV-1048 | Olivia Martin olivia@example.com | Pro License | 2026-10-07 | Paid | $249.00 | ||
| INV-1047 | Jackson Lee jackson@example.com | Team License | 2026-10-07 | Pending | $129.00 | ||
| INV-1046 | Isabella Nguyen isabella@example.com | Personal License | 2026-10-06 | Paid | $49.00 | ||
| INV-1045 | William Kim will@example.com | Team License | 2026-10-06 | Refunded | $129.00 | ||
| INV-1044 | Sofia Davis sofia@example.com | Personal License | 2026-10-05 | Paid | $49.00 | ||
| INV-1043 | Budi Santoso budi@example.com | Pro License | 2026-10-05 | Failed | $249.00 | ||
| INV-1042 | Ayu Lestari ayu@example.com | Personal License | 2026-10-04 | Paid | $49.00 | ||
| INV-1041 | Liam Johnson liam@example.com | Team License | 2026-10-04 | Paid | $129.00 | ||
| INV-1040 | Emma Wilson emma@example.com | Pro License | 2026-10-03 | Pending | $249.00 | ||
| INV-1039 | Rizky Pratama rizky@example.com | Personal License | 2026-10-03 | Paid | $49.00 |
12 rows
API reference
DataTable
| Prop | Type | Default |
|---|---|---|
columns | DataTableColumnDef<TData>[]From createDataTableColumnHelper<TData>(). Required. | — |
data | TData[]The rows. Required. | — |
getRowId | (row: TData) => stringA stable id, so selection survives sorting and paging. | — |
searchPlaceholder | stringThe global search field. | "Search..." |
filters | { column; title; options }[]Faceted filters; their columns need filterFn: "oneOf". | [] |
pageSizes | number[]Rows per page choices; the first is the default. | [10, 20, 50] |
toolbar | (table) => ReactNodeExtra toolbar content, e.g. bulk actions. | — |
exportable | boolean | { filename?, formats?, columns?, extraColumns? }An Export menu (CSV, Excel .xlsx) for the rows the search and filters leave, across pages, or the selected ones, with the visible columns. columns: per column id, { label, value(row) } or false; extraColumns: [{ label, value(row) }] only in the file. The file is named filename-YYYY-MM-DD. | false |
emptyMessage | stringShown when nothing matches. | "No results." |
DataTableColumnHeader
| Prop | Type | Default |
|---|---|---|
column / title | A sortable header button. | — |
dataTableSelectColumn()
A checkbox column for selecting rows.
Keyboard
| Keys | Action |
|---|---|
| Tab | Move through search, filters, headers, row checkboxes and paging |
| EnterorSpace | Sort by a header, toggle a checkbox |
Accessibility
- A real <table>; sortable headers carry aria-sort and say what clicking does.
- Checkboxes are labelled (“Select row”, “Select all rows on this page”).