Skip to Content

Data Table

A powerful data table component built on TanStack Table  with sorting, filtering, pagination, and row selection.

Features

  • Sorting: Click column headers to sort ascending, descending, or clear
  • Pagination: Built-in page navigation with configurable rows per page
  • Row Selection: Checkbox-based row selection with select all support
  • Column Visibility: Toggle column visibility via dropdown
  • Column Header Actions: Reusable header component with sort and hide options
  • Flexible Columns: Define columns with custom renderers, formatters, and actions

Installation

npx shadcn@latest add @uipath/data-table

This component requires the following dependencies:

  • @tanstack/react-table - Table state management and utilities
  • lucide-react - Icons
  • table - Base table primitives
  • button - Button component
  • dropdown-menu - Dropdown menu component
  • select - Select component (for rows per page)

Usage

1. Define your columns

"use client" import type { ColumnDef } from "@/components/ui/data-table" import { DataTableColumnHeader } from "@/components/ui/data-table" type Payment = { id: string amount: number status: "pending" | "processing" | "success" | "failed" email: string } export const columns: ColumnDef<Payment>[] = [ { accessorKey: "status", header: ({ column }) => ( <DataTableColumnHeader column={column} title="Status" /> ), }, { accessorKey: "email", header: ({ column }) => ( <DataTableColumnHeader column={column} title="Email" /> ), }, { accessorKey: "amount", header: ({ column }) => ( <DataTableColumnHeader column={column} title="Amount" /> ), cell: ({ row }) => { const formatted = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", }).format(row.getValue("amount")) return <div className="text-right font-medium">{formatted}</div> }, }, ]

2. Render the DataTable

Use the useDataTable hook to manage all table state, then spread it into DataTable:

"use client" import { DataTable } from "@/components/ui/data-table" import { useDataTable } from "@/hooks/use-data-table" import { columns } from "./columns" export default function PaymentsPage({ data }: { data: Payment[] }) { const tableState = useDataTable({ data, columns, storageKey: "payments", }) return <DataTable {...tableState} /> }

Composable Helpers

The data table exports additional components for building advanced table UIs:

DataTableColumnHeader

A reusable column header with a dropdown for sorting and hiding columns.

import { DataTableColumnHeader } from "@/components/ui/data-table" { accessorKey: "email", header: ({ column }) => ( <DataTableColumnHeader column={column} title="Email" /> ), }

DataTablePagination

A standalone pagination component. The DataTable includes this by default, but you can also use it separately when building custom table layouts.

import { DataTablePagination } from "@/components/ui/data-table" <DataTablePagination table={table} />

DataTableViewOptions

A column visibility toggle dropdown. Use this in a toolbar above the table.

import { DataTableViewOptions } from "@/components/ui/data-table" <DataTableViewOptions table={table} />

State Management Hooks

The Data Table requires external state for sorting, filtering, pagination, column visibility, column order, and row selection. Two hooks are provided that manage this state and return props compatible with DataTable:

useDataTable

A generic hook for managing Data Table state with any data source. It handles persisting sorting, column visibility, and column order to localStorage.

Installation

npx shadcn@latest add @uipath/use-data-table

Usage

The hook returns an object that can be spread directly into DataTable:

"use client" import { DataTable } from "@/components/ui/data-table" import { useDataTable } from "@/hooks/use-data-table" import { columns } from "./columns" export default function PaymentsPage({ data }: { data: Payment[] }) { const tableState = useDataTable({ data, columns, storageKey: "payments", defaultVisibleColumns: ["status", "email", "amount"], }) return <DataTable {...tableState} /> }

Options

OptionTypeDescription
dataTData[]The data array to display
columnsColumnDef<TData>[]TanStack Table column definitions
storageKeystringKey used to persist state in localStorage
isLoadingbooleanOptional loading state (default: false)
defaultColumnOrderstring[]Initial column order (defaults to column definition order)
defaultVisibleColumnsstring[]Initially visible columns (defaults to all)

useEntityDataTable

A specialized hook for entity-based tables that integrates with VSS (Virtual Solution Storage). It extends useDataTable by automatically generating column definitions from entity metadata and fetching data via useLiveQuery.

Installation

npx shadcn@latest add @uipath/use-entity-data-table

Usage

"use client" import { DataTable } from "@/components/ui/data-table" import { useEntityDataTable } from "@/hooks/use-entity-data-table" export default function EntityPage({ entity }: { entity: VssEntity }) { const tableState = useEntityDataTable({ entity, storageKey: "my-entity", initialVisibleColumnCount: 6, systemFields: ["Id"], }) return <DataTable {...tableState} /> }

Options

OptionTypeDescription
entityVssEntityThe VSS entity definition (provides fields and metadata)
storageKeystringKey used to persist state (defaults to entity-{name})
initialVisibleColumnCountnumberNumber of columns visible by default (default: 8)
systemFieldsstring[]Fields to exclude from the table (default: ["Id"])
columnOrderstring[]Explicit column order override
extraColumnsExtraColumn[]Additional columns injected at "start" or "end"
columnOverridesRecord<string, (def) => def>Per-column definition overrides

Persisted State

Both hooks automatically persist the following state to localStorage:

  • Sorting — stored under entity-table-sorting-{storageKey}
  • Column visibility — stored under entity-table-columns-{storageKey}
  • Column order — stored under entity-table-column-order-{storageKey}
  • Global filter (entity hook only) — stored under entity-table-global-filter-{storageKey}

Row Selection

Add a selection column using the Checkbox component:

import { Checkbox } from "@/components/ui/checkbox" const columns: ColumnDef<Payment>[] = [ { id: "select", header: ({ table }) => ( <Checkbox checked={ table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && "indeterminate") } onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)} aria-label="Select all" /> ), cell: ({ row }) => ( <Checkbox checked={row.getIsSelected()} onCheckedChange={(value) => row.toggleSelected(!!value)} aria-label="Select row" /> ), enableSorting: false, enableHiding: false, }, // ... other columns ]