Data Table
Tables for dashboards built on TanStack Table, with sorting, search, filters, row selection and pagination. Rows restack into labelled cards on narrow screens.
Full Featured
Search, status and plan filters with counts, a column menu and page sizes. Select rows to export them as CSV or email them. Shift-click a header to sort by more than one column.
| Status | |||||
|---|---|---|---|---|---|
| Harborbilling@harbor.app | Past due | Enterprise | $1,395 | Sep 17, 2025 | |
| Wren & Cobilling@wren.co | Active | Team | $768 | Apr 26, 2024 | |
| Stackwisebilling@stackwise.io | Active | Team | $528 | Dec 14, 2025 | |
| Sablebilling@sable.so | Active | Team | $504 | May 5, 2025 | |
| Verdantbilling@verdant.farm | Past due | Pro | $348 | May 25, 2025 | |
| Fieldnotesbilling@fieldnotes.co | Active | Pro | $288 | Apr 6, 2024 | |
| Tidewaterbilling@tidewater.co | Past due | Team | $264 | Jan 21, 2024 | |
| Brightpathbilling@brightpath.dev | Active | Team | $240 | Jun 12, 2025 |
1–8 of 22
Sortable
Select a column header to sort by it, and again to reverse the order. On narrow screens, where the headers are hidden, use the sort menu instead.
| / | 18,420 | 61,240 | 38% | 1m 42s |
| /pricing | 9,312 | 21,860 | 29% | 2m 28s |
| /docs/getting-started | 7,845 | 19,470 | 22% | 4m 23s |
| /blog/launch-week | 5,127 | 8,930 | 61% | 1m 11s |
| /docs/components | 4,906 | 12,310 | 34% | 3m 04s |
| /changelog | 3,284 | 6,120 | 47% | 1m 35s |
| /signup | 2,971 | 4,410 | 18% | 0m 52s |
Inline Bars
Revenue by product, with a bar scaled to the top product and each product's share of the total.
| Product | Units | Revenue | Share |
|---|---|---|---|
| Studio Display 27"Displays | 112 | $48,920 | 29% |
| Wireless headphonesAudio | 287 | $41,370 | 24% |
| Ergonomic chairFurniture | 84 | $36,540 | 21% |
| Mechanical keyboardAccessories | 179 | $21,480 | 13% |
| USB-C dockAccessories | 144 | $12,960 | 8% |
| Desk speakersAudio | 97 | $8,730 | 5% |
Trends
Campaign conversions and cost per conversion with their change, plus a 14-day sparkline.
| Campaign | Spend | Conversions | Cost per conversion | Conversions by day |
|---|---|---|---|---|
| Brand keywordsPaid search | $7,420 | 650 +27% | $11.42 -19.6% | |
| Autumn launchPaid social | $9,860 | 422 +57.5% | $23.36 -26.1% | |
| RetargetingDisplay | $4,310 | 161 -33.2% | $26.77 +41.6% | |
| Weekly newsletterEmail | $320 | 167 +12.1% | $1.92 -8.8% |
Status
Services with their status, latency and error rate. Sorted by status, worst first.
| Webhooksap-southeast-2 | Partial outage | 2,310 ms | 12.6% |
| Searcheu-west-1 | Degraded performance | 642 ms | 1.84% |
| Billingus-west-2 | Maintenance | — | — |
| API gatewayus-east-1 | Operational | 118 ms | 0.02% |
| Authus-east-1 | Operational | 96 ms | 0.05% |
| Media uploadseu-central-1 | Operational | 184 ms | 0.11% |
Pagination
Recent orders, five to a page.
| Customer | Order | Date | Status | Amount |
|---|---|---|---|---|
| Ava Thompsonava@northwind.io | #4821 | Sep 25 | Paid | $42.00 |
| Ethan Brooksethan@quanta.ai | #4820 | Sep 25 | Paid | $115.49 |
| Zoe Williamszoe@harbor.app | #4819 | Sep 25 | Pending | $188.98 |
| Noah Patelnoah@fieldnotes.co | #4818 | Sep 24 | Paid | $261.00 |
| Maya Chenmaya@loop.studio | #4817 | Sep 24 | Refunded | $334.49 |
1–5 of 18
Usage
useDataTable creates a TanStack Table instance with sorting, filtering, search, pagination, row selection and column visibility. It takes every TanStack Table option. DataTableContent renders it, laying out each cell from its column's meta.
const columnHelper = createDataTableColumnHelper<Order>()
const columns = columnHelper.columns([
createDataTableSelectColumn<Order>({ getRowLabel: (row) => row.customer }),
columnHelper.accessor('customer', { header: 'Customer', meta: { primary: true } }),
columnHelper.accessor('status', { header: 'Status' }),
columnHelper.accessor('amount', {
cell: ({ getValue }) => `$${getValue().toFixed(2)}`,
header: 'Amount',
meta: { align: 'end' },
}),
])
function Orders({ orders }: { orders: Order[] }) {
const table = useDataTable({ columns, data: orders, pageSize: 10 })
return (
<Card className='@container/data-table gap-0 pb-0'>
<div className='flex flex-wrap items-center gap-2 px-6 pb-3'>
<DataTableSearch table={table} />
<DataTableFacetFilter column={table.getColumn('status')} />
<DataTableReset table={table} />
<DataTableViewOptions className='ml-auto' table={table} />
</div>
<DataTableContent caption='Orders' table={table} />
<DataTablePagination className='border-t px-6 py-3' table={table} />
</Card>
)
}createDataTableSelectColumn adds a checkbox to each row. Its getRowLabel names each checkbox after the row ("Select Northwind"), so a screen reader can tell the rows apart; without it, or for an empty label, the checkbox reads "Select row".
Keep data and columns stable between renders, at module scope or in useMemo. Without pageSize, or pagination in initialState or state, the table shows every row. For server-side data, pass manualSorting, manualFiltering and manualPagination with rowCount, and control the state with state and its on[State]Change callbacks.
Column meta
| Option | Description |
|---|---|
label | Names the column in menus and labels its values when stacked. Defaults to a string header. |
align | 'end' right-aligns the column, for numbers. |
primary | The row's title: spans the full width when stacked, without a label. |
truncate | Fills the spare width and truncates long text. |
cellClassName | Classes for the column's cells. |
headerClassName | Classes for the column's header. |
hideLabelWhenStacked | Leaves its values without a label when stacked, for a column of row actions. |
The layout primitives, DataTable, DataTableRow, DataTableCell and friends, still render static tables without TanStack Table, as in the Inline Bars and Trends examples.