Table
Headless, sortable, filterable, and paginated data tables powered by TanStack Table v8. Full control over styling with zero opinion on markup.
TanStack Table v8TypeScriptSortableFilterablePaginated
01
Theme Preview
The table adapts seamlessly to both themes via Tailwind's class-based dark mode. Each variant below is rendered with forced styling — independent of the current app theme — so you can compare them side by side.
Lightbg-white · border-slate-200
| Name | Role | Status | |
|---|---|---|---|
| Alice Johnson | alice@example.com | admin | active |
| Bob Smith | bob@example.com | editor | active |
| Carol Williams | carol@example.com | viewer | active |
| David Brown | david@example.com | editor | inactive |
| Eva Martinez | eva@example.com | admin | active |
Darkbg-[#0d1117] · border-[#1f2937]
| Name | Role | Status | |
|---|---|---|---|
| Alice Johnson | alice@example.com | admin | active |
| Bob Smith | bob@example.com | editor | active |
| Carol Williams | carol@example.com | viewer | active |
| David Brown | david@example.com | editor | inactive |
| Eva Martinez | eva@example.com | admin | active |
02
Live Demo
Fully interactive — try sorting columns, filtering rows, and navigating pages. The table responds to the current app theme automatically.
Name | Email | Role | Status | Created |
|---|---|---|---|---|
| Alice Johnson | alice@example.com | admin | active | Jan 15, 2024 |
| Bob Smith | bob@example.com | editor | active | Feb 10, 2024 |
| Carol Williams | carol@example.com | viewer | active | Feb 20, 2024 |
| David Brown | david@example.com | editor | inactive | Mar 5, 2024 |
| Eva Martinez | eva@example.com | admin | active | Mar 12, 2024 |
| Frank Garcia | frank@example.com | viewer | active | Mar 18, 2024 |
| Grace Lee | grace@example.com | editor | active | Apr 1, 2024 |
| Henry Wilson | henry@example.com | viewer | inactive | Apr 10, 2024 |
Page 1 of 3 (20 rows)
03
Column Config
Define columns with ColumnDef<T>. Wrap in useMemo to prevent re-instantiation on every render.
components/UserTable.tsx
const columns = useMemo<ColumnDef<User>[]>(() => [ { accessorKey: "name", header: "Name", cell: (info) => ( <span className="font-medium">{info.getValue<string>()}</span> ), }, { accessorKey: "role", header: "Role", cell: (info) => ( <span className="rounded-full bg-slate-100 px-2.5 py-0.5 text-xs font-medium capitalize dark:bg-slate-800"> {info.getValue<string>()} </span> ), }, { accessorKey: "status", header: "Status", cell: (info) => { const status = info.getValue<string>(); return ( <span className={`rounded-full px-2.5 py-0.5 text-xs font-medium ${ status === "active" ? "bg-green-100 text-green-700 dark:bg-green-900/40 dark:text-green-400" : "bg-red-100 text-red-700 dark:bg-red-900/40 dark:text-red-400" }`}> {status} </span> ); }, }, ], []);
04
Props
| Prop | Type | Required | Description |
|---|---|---|---|
data | T[] | required | Array of row data to display in the table. |
columns | ColumnDef<T>[] | required | Column definitions including header, accessor, and optional cell renderer. |
pageSize | number | optional | Number of rows shown per page. Defaults to 8. |
globalFilter | string | optional | Text filter applied across all column values simultaneously. |
sorting | SortingState | optional | Controlled sorting state. Pair with onSortingChange for external control. |