Make your AI a shadcn expert

Shadcn Data Table

React data table for payments, users, and admin lists. Built with TypeScript and Tailwind CSS for Next.js using Table and TanStack Table — sort, filter, paginate.

There is no DataTable in components/ui. You wire TanStack Table to the Table primitives: a features object, column defs, then useTable. Use it for payments, users, or any admin list that needs sort, filter, pagination, or row selection.

Scroll to load preview...

Looking for a neobrutalism version for shadcn?

Same data table, thicker borders. The NeoBrutalism data table is the kit if you want that look.

Usage

import {
  flexRender,
  tableFeatures,
  useTable,
} from "@tanstack/react-table"
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"
const table = useTable({ features, data, columns })

return (
  <Table>
    <TableHeader>
      {table.getHeaderGroups().map((headerGroup) => (
        <TableRow key={headerGroup.id}>
          {headerGroup.headers.map((header) => (
            <TableHead key={header.id}>
              {flexRender(header.column.columnDef.header, header.getContext())}
            </TableHead>
          ))}
        </TableRow>
      ))}
    </TableHeader>
    <TableBody>
      {table.getRowModel().rows.map((row) => (
        <TableRow key={row.id} data-state={row.getIsSelected() && "selected"}>
          {row.getVisibleCells().map((cell) => (
            <TableCell key={cell.id}>
              {flexRender(cell.column.columnDef.cell, cell.getContext())}
            </TableCell>
          ))}
        </TableRow>
      ))}
    </TableBody>
  </Table>
)

features is the opt-in list. Sorting does nothing until rowSortingFeature and createSortedRowModel() are on it.

Composition

TableHead
TableCell

There is no DataTable export. useTable owns the instance; Table is the markup.

Basic Table

Status, email, amount. No sort, no filter — just useTable over the rows.

Scroll to load preview...

Pagination

rowPaginationFeature and createPaginatedRowModel(). Previous / next call table.previousPage() and table.nextPage().

Scroll to load preview...

Sorting

Put a Button in the header and call column.toggleSorting. Wire sorting into state.

Scroll to load preview...

Filtering

table.getColumn("email")?.setFilterValue on an Input. The column must have an accessorKey.

Scroll to load preview...

Visibility

column.toggleVisibility from a Dropdown Menu. Hide a column on first render with columnVisibility.

Scroll to load preview...

Row Selection

A Checkbox column. Header uses toggleAllPageRowsSelected. data-state="selected" paints the row.

Scroll to load preview...

RTL

Wrap with DirectionProvider and dir="rtl". Amounts use text-end so they stay on the reading end.

Scroll to load preview...

API

These are useTable options from TanStack Table. There is no DataTable export.

Prop

Type

ColumnDef

Prop

Type

flexRender draws header and cell. Empty body is one TableRow with a colSpan cell.

Notes

Columns own the table

header, cell, sort, and filter live on the column def — not on useTable. Register filterFns and sortFns on features or those column options are no-ops.

There is no components/ui/data-table.tsx. Keep columns next to the page that fetches the rows.

With other components

Questions

Was this page helpful?

Sign in to leave feedback.