Data Table

TanStack-powered data table: faceted, text, range and date filters, sortable columns, column visibility, row selection and pagination, with page, sort and filters kept in the URL. One useDataTable hook drives it — pass pageCount to query server-side, or omit it to sort, filter and page a local array in memory. Ships as a folder of composable parts.

Example

Installation

npx shadcn@latest add https://hirael.com/r/data-table.json

API

<DataTable />

+ native element props
PropTypeDefault
table*TanstackTable<TData>
actionBarReact.ReactNode

<DataTableToolbar />

+ native element props
PropTypeDefault
table*Table<TData>

<DataTableColumnHeader />

+ native element props
PropTypeDefault
column*Column<TData, TValue>
label*string

<DataTablePagination />

+ native element props
PropTypeDefault
table*Table<TData>
pageSizeOptionsnumber[][10, 20, 30, 40, 50]

<DataTableViewOptions />

+ native element props
PropTypeDefault
table*Table<TData>
disabledboolean

<DataTableFacetedFilter />

PropTypeDefault
columnColumn<TData, TValue>
titlestring
options*Option[]
multipleboolean

<DataTableSliderFilter />

PropTypeDefault
column*Column<TData, unknown>
titlestring

<DataTableDateFilter />

PropTypeDefault
column*Column<TData, unknown>
titlestring
multipleboolean

<DataTableSkeleton />

+ native element props
PropTypeDefault
columnCount*number
rowCountnumber10
filterCountnumber0
cellWidthsstring[]["auto"]
withViewOptionsbooleantrue
withPaginationbooleantrue
shrinkZerobooleanfalse

Component source

components/data-table/data-table.tsx
"use no memo";
"use client";

import { DataTablePagination } from "./data-table-pagination";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/registry/hirael/ui/table";
import { getColumnPinningStyle } from "./data-table-utils";
import { cn } from "@/lib/utils";
import { flexRender, type Table as TanstackTable } from "@tanstack/react-table";
import type * as React from "react";

interface DataTableProps<TData> extends React.ComponentProps<"div"> {
  table: TanstackTable<TData>;
  actionBar?: React.ReactNode;
}

export function DataTable<TData>({
  table,
  actionBar,
  children,
  className,
  ...props
}: DataTableProps<TData>) {
  return (
    <div
      data-slot="data-table"
      className={cn("flex w-full flex-col gap-2.5 overflow-auto", className)}
      {...props}
    >
      {children}
      <div
        data-slot="data-table-content"
        className="overflow-hidden rounded-md border"
      >
        <Table>
          <TableHeader>
            {table.getHeaderGroups().map((headerGroup) => (
              <TableRow key={headerGroup.id}>
                {headerGroup.headers.map((header) => (
                  <TableHead
                    key={header.id}
                    colSpan={header.colSpan}
                    style={{
                      ...getColumnPinningStyle({ column: header.column }),
                    }}
                  >
                    {header.isPlaceholder
                      ? null
                      : flexRender(
                          header.column.columnDef.header,
                          header.getContext(),
                        )}
                  </TableHead>
                ))}
              </TableRow>
            ))}
          </TableHeader>
          <TableBody>
            {table.getRowModel().rows?.length ? (
              table.getRowModel().rows.map((row) => (
                <TableRow
                  key={row.id}
                  data-state={row.getIsSelected() && "selected"}
                >
                  {row.getVisibleCells().map((cell) => (
                    <TableCell
                      key={cell.id}
                      style={{
                        ...getColumnPinningStyle({ column: cell.column }),
                      }}
                    >
                      {flexRender(
                        cell.column.columnDef.cell,
                        cell.getContext(),
                      )}
                    </TableCell>
                  ))}
                </TableRow>
              ))
            ) : (
              <TableRow>
                <TableCell
                  colSpan={table.getAllColumns().length}
                  className="h-24 text-center"
                >
                  No results.
                </TableCell>
              </TableRow>
            )}
          </TableBody>
        </Table>
      </div>
      <div className="flex flex-col gap-2.5">
        <DataTablePagination table={table} />
        {actionBar &&
          table.getFilteredSelectedRowModel().rows.length > 0 &&
          actionBar}
      </div>
    </div>
  );
}

Dependencies

shadcn registry

badgebuttoncalendarcommanddropdown-menuinputlabelpopoverselectseparatorskeletonslidertable

npm

@tanstack/react-tablelucide-reactnuqsreact-day-pickerzod