Skip to content

Shadcn Data Table

The shadcn/ui data table is a pattern, not a single component: it pairs the styled Table primitive with TanStack Table to add sorting, filtering, pagination, and row selection. shadcn gives you the accessible markup; TanStack Table is the headless engine for the data logic. Data tables drive dashboards, order lists, and admin screens across ShadcnStore blocks.

Key features

  • Styled Table primitive plus the TanStack Table engine.
  • Sorting, filtering, pagination, and row selection.
  • Per-row action menus via Dropdown Menu.
  • Semantic table markup with aria-sort on sorted headers.
  • Responsive with horizontal scroll on small screens.

Installation

Add the Table primitive, then install TanStack Table:

bash
npx shadcn@latest add table
npm install @tanstack/react-table

The Table primitive

For a static table, the primitive alone is enough:

tsx
import {
  Table,
  TableHeader,
  TableBody,
  TableRow,
  TableHead,
  TableCell,
} from "@/components/ui/table"

<Table>
  <TableHeader>
    <TableRow>
      <TableHead>Invoice</TableHead>
      <TableHead>Amount</TableHead>
    </TableRow>
  </TableHeader>
  <TableBody>
    <TableRow>
      <TableCell>INV-001</TableCell>
      <TableCell>$250.00</TableCell>
    </TableRow>
  </TableBody>
</Table>

Sorting and filtering

A data table adds interaction on top of the primitive: a filter input, sortable columns, and an empty state. Type in the filter and click the Amount header to sort.

The demo keeps its own useState for the filter text and sort direction, then derives the visible rows. For large datasets, move sorting, filtering, and pagination into TanStack Table below.

Add TanStack Table

Define columns and pass your data to useReactTable, enabling the row models for the features you need:

tsx
import {
  useReactTable,
  getCoreRowModel,
  getSortedRowModel,
  getPaginationRowModel,
  flexRender,
} from "@tanstack/react-table"

const table = useReactTable({
  data,
  columns,
  getCoreRowModel: getCoreRowModel(),
  getSortedRowModel: getSortedRowModel(),
  getPaginationRowModel: getPaginationRowModel(),
})

Render the header and rows with flexRender, then bind:

  • Sorting to header clicks with column.toggleSorting().
  • Pagination to Previous/Next Buttons with table.previousPage() and table.nextPage().
  • Filtering to an Input with column.setFilterValue().
  • Row selection to a checkbox column with row.toggleSelected().

Row actions

Put a per-row Dropdown Menu in the last column for actions like view, edit, and delete.

Accessibility

  • Keep semantic table markup: real <th> headers with scope so screen readers announce column and row relationships.
  • When sorting is active, reflect it with aria-sort on the sorted header.
  • Provide a visible caption or heading that names what the table contains.

When to use the Data Table

Use a data table for structured rows of records the user scans, sorts, filters, or paginates: orders, users, transactions, and inventory. For a small set of key-value details, a Card or description list is clearer. For a handful of static rows with no interaction, the Table primitive alone is enough; reach for TanStack Table only when you need sorting, filtering, or pagination.

Used in these blocks

A data table combines the Table primitive with a Button toolbar, an Input filter, a Badge for status cells, and a Dropdown Menu for row actions. Group views with Tabs.

FAQ

What is the shadcn data table?

The shadcn data table is a pattern that combines the styled Table primitive with TanStack Table to add sorting, filtering, pagination, and row selection.

Does the shadcn data table use TanStack Table?

Yes. shadcn provides the Table UI and a guide to wire TanStack Table (react-table) as the headless engine for data logic.

How do I add sorting and pagination?

Enable getSortedRowModel and getPaginationRowModel in useReactTable, then bind sort toggles to column headers and Previous/Next buttons to the table's pagination API.

How do I make the data table responsive?

Wrap the table in a container with overflow-x-auto so it scrolls horizontally on small screens, or hide lower-priority columns at narrow breakpoints.