Data Table
NewA sortable, searchable table. Rows glide into their new order, matches are highlighted, and selecting rows slides up a bulk action bar.
motionlucide-reactutils@soultel/use-reduced-motion-safe
8 rows
| Parcel CoINV-1039 | $4,120 | |
| Kite AnalyticsINV-1037 | $3,350 | |
| Northwind TradersINV-1042 | $2,480 | |
| Orbit FitnessINV-1035 | $1,875 | |
| Lumen LabsINV-1041 | $1,290 | |
| FieldnoteINV-1038 | $980 | |
| Tilde StudioINV-1040 | $760 | |
| Acme BakeryINV-1036 | $410 |
Installation
$ pnpm dlx shadcn@latest add @soultel/data-tableNo namespace set up? npx shadcn@latest add https://asafefe.dev/r/data-table.json works too.
Manual installation
- 1. Install the dependencies.
terminal1 lines npm install motion lucide-react - 2. Copy the source from the Code tab into components/data-table.tsx.
Usage
import { DataTable, highlight, type DataTableColumn } from "@/components/data-table"
type Invoice = { id: string; customer: string; amount: number; status: string }
const columns: DataTableColumn<Invoice>[] = [
{ key: "customer", header: "Customer", accessor: (r) => r.customer, sortable: true },
{ key: "status", header: "Status", accessor: (r) => r.status, cell: (r, q) => <b>{highlight(r.status, q)}</b> },
{ key: "amount", header: "Amount", accessor: (r) => r.amount, sortable: true, align: "right" },
]
export function Invoices({ rows }: { rows: Invoice[] }) {
return (
<DataTable
data={rows}
columns={columns}
getRowId={(r) => r.id}
selectable
bulkActions={(ids, clear) => <button onClick={() => { exportCsv(ids); clear() }}>Export</button>}
/>
)
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| data | T[] | - | Rows. |
| columns | DataTableColumn<T>[] | - | key, header, accessor, and optional cell, sortable, align, hideBelow. |
| getRowId | (row: T) => string | - | Stable id per row. |
| getRowLabel | (row: T) => string | - | Name read out by each row checkbox. |
| selectable | boolean | false | Adds checkboxes and the bulk action bar. |
| selected / defaultSelected | string[] | - | Controlled or initial selected ids, with onSelectedChange. |
| bulkActions | (ids, clear) => ReactNode | - | Buttons in the bulk action bar. |
| sort / defaultSort | { key: string; direction: "asc" | "desc" } | null | - | Controlled or initial sort, with onSortChange. Headers cycle asc, desc, off. |
| searchable | boolean | true | Show the search field. Matches get a highlight. |
| empty | (query: string) => ReactNode | - | Custom empty state. |
| highlight(text, query) | => ReactNode | - | Exported helper for custom cells. |
