Pro Components

Base Components

Data Table

Powerful table and datagrids built using TanStack Table, with sorting, filtering, pagination, and row actions.

Example

StatusEmail
Amount
pendingalex.morgan@blakeui.com
$100.00
processingsam.rivera@blakeui.com
$125.00
successjordan.hale@blakeui.com
$316.00
successcasey.moore@blakeui.com
$242.00
processingmorgan.reid@blakeui.com
$837.00
successavery.blake@blakeui.com
$874.00
failedriley.chen@blakeui.com
$721.00

Introduction

The Data Table is built with the base Table component and TanStack Table. It gives you a flexible, headless way to build tables with:
  • Column definitions and custom cells
  • Pagination
  • Row actions (e.g. dropdown menu per row)
  • Optional sorting and filtering (you can extend the example below)
This guide follows the Blake UI data table approach: define columns and data, then render with <DataTable />.

Prerequisites

Define the shape of your data and the column definitions. Example:
type Payment = {
  id: string;
  amount: number;
  status: "pending" | "processing" | "success" | "failed";
  email: string;
};

const columns: ColumnDef<Payment>[] = [
  { accessorKey: "status", header: "Status" },
  { accessorKey: "email", header: "Email" },
  {
    accessorKey: "amount",
    header: () => <div className="text-right">Amount</div>,
    cell: ({ row }) => {
      const amount = parseFloat(row.getValue("amount"));
      return (
        <div className="text-right font-medium">
          {new Intl.NumberFormat("en-US", {
            style: "currency",
            currency: "USD",
          }).format(amount)}
        </div>
      );
    },
  },
];

Usage

import { DataTable } from "@/components/ui/data-table";

<DataTable columns={columns} data={data} />;
The DataTable component accepts:
  • columns – Array of TanStack ColumnDef<TData, TValue>
  • data – Array of row data

Basic Table

A minimal table only needs column definitions and data. Use accessorKey to bind a column to a field and optional header and cell for custom rendering.
StatusEmailAmount
successjordan.hale@blakeui.com$316.00
processingmorgan.reid@blakeui.com$837.00

Row Actions

Add an id: "actions" column with a custom cell that renders a dropdown (or buttons) for each row. Use row.original to access the row data.
{
  id: "actions",
  cell: ({ row }) => {
    const payment = row.original;
    return (
      <DropdownMenu>
        <DropdownMenuTrigger asChild>
          <Button variant="secondary" size="sm" className="h-8 w-8 p-0">
            <MoreHorizontal className="h-4 w-4" />
          </Button>
        </DropdownMenuTrigger>
        <DropdownMenuContent align="end">
          <DropdownMenuItem onClick={() => navigator.clipboard.writeText(payment.id)}>
            Copy payment ID
          </DropdownMenuItem>
          <DropdownMenuItem>View customer</DropdownMenuItem>
        </DropdownMenuContent>
      </DropdownMenu>
    );
  },
}

Pagination

The included DataTable component uses getPaginationRowModel() so rows are paginated (default page size 10). It renders Previous/Next buttons; you can extend it with page size selector and page count using the same TanStack patterns described in this page.

Extending

You can add:
  • SortinggetSortedRowModel(), onSortingChange, and sortable header cells
  • FilteringgetFilteredRowModel(), onColumnFiltersChange, and an input that calls table.getColumn("email")?.setFilterValue(value)
  • Row selection – checkbox column and getFilteredSelectedRowModel()
See the TanStack Table docs for full examples.

API Reference

DataTable

columns*ColumnDef<TData, TValue>[]
Default: -
data*TData[]
Default: -
PropTypeDefaultDescription
columns*ColumnDef<TData, TValue>[]--
data*TData[]--

On this page