Back to Playground

Reference DataTable

A dense table that still feels readable.

Sorting, pagination, row selection, visibility controls, and column drag-and-drop on 1,000 generated employee records.

Records
1,000
Columns
7
Actions
Sort + select
Layout
Drag headers

Column UX: drag by the grip, click headers to sort, hide columns from the Columns menu.

Data: 1,000 faker-generated employees, paginated locally for fast interaction.

Reference logic: built on the copied DataTable APIs rather than a simplified mock.

Usage

TSX
import { DataTable } from '@/components/dataTable/DataTable'
import type { ColumnGroup } from '@/components/dataTable/types'

type User = { id: number; name: string; email: string; status: string; salary: number }

export default function EmployeeTable() {
  const columnsConfig: ColumnGroup<User>[] = [{
    id: 'main',
    columns: [
      { id: 'name', accessorKey: 'name', header: 'Name', enableSorting: true },
      { id: 'email', accessorKey: 'email', header: 'Email', enableSorting: true },
      { id: 'status', accessorKey: 'status', header: 'Status',
        cell: ({ getValue }) => <Badge>{String(getValue())}</Badge> },
      { id: 'salary', accessorKey: 'salary', header: 'Salary',
        cell: ({ getValue }) => `$${(getValue() as number).toLocaleString()}` },
    ]
  }]

  const fetchData = async (params) => {
    // params: { page, pageSize, sorting, filters }
    const rows = await getUsers(params)
    return { rows, rowCount: rows.length }
  }

  return (
    <DataTable
      tag="employees"
      title="Employee Directory"
      fetchData={fetchData}
      columnsConfig={columnsConfig}
      operations={{ view: { component: ViewUser, displayMode: 'sheet', width: 'md' } }}
      enableSelection
      showPagination
    />
  )
}

What is this DataTable?

A production-style React DataTable built with TanStack Table. It renders a pageable, sortable grid over 1,000 generated employee records — but the component itself is dataset-agnostic. Pass it a fetch function, a column configuration, and optional row operations, and it handles the rest.

This is the kind of table you reach for in admin panels, ERP modules, and internal business applications: dense, fast, keyboard-friendly, and built around real-world interactions like selecting a batch of rows to act on.

How it works

The table is configured through a typed column configuration: each column declares its accessor, header, sorting behaviour, and optional custom cell renderer. Grouping lets you bundle columns under a shared header. Pagination, sorting, and row selection state live in TanStack Table, while the fetch function supplies the data for the active page.

Column drag-and-drop reordering uses a grip handle on each header. The Columns menu toggles visibility, and the selection summary updates as rows are checked. A row "view" operation opens a detail sheet driven by the same operation pipeline the table exposes to custom actions.

Features

  • Paginated 1,000-row dataset
  • Sortable columns across all data types
  • Row selection with selected-row summary
  • Column visibility picker
  • Drag-and-drop column reordering
  • Typed column groups and custom cell renderers

When to use a component like this

Reaching for a configurable DataTable pays off when your app renders the same grid pattern across many screens — employee directories, inventory, invoices, audit logs. Centralising sorting, pagination, and selection in one reusable component keeps those screens consistent and cuts per-screen code substantially.

Built with React, TypeScript and TanStack Table. Related demos: the SchemaForm builder playground, which shows how schema-driven forms generate the entry screens that feed grids like this one, and the QueryBuilder playground, which composes the filter payload this table consumes.