Dashboardblocks
Components

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.

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.

Customers
All accounts, by monthly recurring revenue
Customers: All accounts, by monthly recurring revenue
Status
Harborbilling@harbor.appPast dueEnterprise$1,395Sep 17, 2025
Wren & Cobilling@wren.coActiveTeam$768Apr 26, 2024
Stackwisebilling@stackwise.ioActiveTeam$528Dec 14, 2025
Sablebilling@sable.soActiveTeam$504May 5, 2025
Verdantbilling@verdant.farmPast duePro$348May 25, 2025
Fieldnotesbilling@fieldnotes.coActivePro$288Apr 6, 2024
Tidewaterbilling@tidewater.coPast dueTeam$264Jan 21, 2024
Brightpathbilling@brightpath.devActiveTeam$240Jun 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.

Top pages
Last 30 days
Top pages, last 30 days
/18,42061,24038%1m 42s
/pricing9,31221,86029%2m 28s
/docs/getting-started7,84519,47022%4m 23s
/blog/launch-week5,1278,93061%1m 11s
/docs/components4,90612,31034%3m 04s
/changelog3,2846,12047%1m 35s
/signup2,9714,41018%0m 52s

Inline Bars

Revenue by product, with a bar scaled to the top product and each product's share of the total.

Revenue by product
Units sold, revenue and share of total, last 30 days
Revenue by product: Units sold, revenue and share of total, last 30 days
ProductUnitsRevenueShare
Studio Display 27"Displays112$48,92029%
Wireless headphonesAudio287$41,37024%
Ergonomic chairFurniture84$36,54021%
Mechanical keyboardAccessories179$21,48013%
USB-C dockAccessories144$12,9608%
Desk speakersAudio97$8,7305%

Campaign conversions and cost per conversion with their change, plus a 14-day sparkline.

Campaigns
Last 14 days, compared with the previous 14 days
Campaigns: Last 14 days, compared with the previous 14 days
CampaignSpendConversionsCost per conversionConversions by day
Brand keywordsPaid search$7,420650
+27%
$11.42
-19.6%
Autumn launchPaid social$9,860422
+57.5%
$23.36
-26.1%
RetargetingDisplay$4,310161
-33.2%
$26.77
+41.6%
Weekly newsletterEmail$320167
+12.1%
$1.92
-8.8%

Status

Services with their status, latency and error rate. Sorted by status, worst first.

Services
2 of 6 services with issues
Services
Webhooksap-southeast-2Partial outage2,310 ms12.6%
Searcheu-west-1Degraded performance642 ms1.84%
Billingus-west-2Maintenance——
API gatewayus-east-1Operational118 ms0.02%
Authus-east-1Operational96 ms0.05%
Media uploadseu-central-1Operational184 ms0.11%

Pagination

Recent orders, five to a page.

Recent orders
Orders from the last 7 days
Recent orders, page 1 of 4
CustomerOrderDateStatusAmount
Ava Thompsonava@northwind.io#4821Sep 25Paid$42.00
Ethan Brooksethan@quanta.ai#4820Sep 25Paid$115.49
Zoe Williamszoe@harbor.app#4819Sep 25Pending$188.98
Noah Patelnoah@fieldnotes.co#4818Sep 24Paid$261.00
Maya Chenmaya@loop.studio#4817Sep 24Refunded$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.

components/orders-table.tsx
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

OptionDescription
labelNames the column in menus and labels its values when stacked. Defaults to a string header.
align'end' right-aligns the column, for numbers.
primaryThe row's title: spans the full width when stacked, without a label.
truncateFills the spare width and truncates long text.
cellClassNameClasses for the column's cells.
headerClassNameClasses for the column's header.
hideLabelWhenStackedLeaves 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.

On this page