Skip to content

DataTable API

Complete type definitions and prop reference for the DataTable ecosystem.


DataTable

Enterprise-grade data table with automatic client/server mode detection.

Import

tsx
import { DataTable, type DataTableColumn, type DataTableProps, type TableMode, type TableDensity } from '@/shared/ui/components/table/DataTable'

Props

DataTableProps<T>

PropTypeDefaultDescription
Data & Columns
columnsDataTableColumn<T>[]RequiredColumn definitions
dataT[]RequiredArray of data objects
Mode Configuration
mode'client' | 'server'Auto-detectTable processing mode. Auto-detects based on callbacks
Loading & Error States
isLoadingbooleanfalseShow loading spinner
isErrorbooleanfalseShow error state
loadingContentReactNodeDefault spinnerCustom loading content
errorContentReactNodeDefault errorCustom error content
emptyContentReactNode"No results found"Custom empty state
Server-Side Callbacks
onSortingChange(sorting: SortingState) => void-Called when sorting changes (triggers server mode)
onColumnFiltersChange(filters: ColumnFiltersState) => void-Called when filters change (triggers server mode)
onPaginationChange(pagination: PaginationState) => void-Called when pagination changes (triggers server mode)
onRowSelectionChange(rows: T[]) => void-Called when row selection changes
onGlobalFilterChange(search: string) => void-Called when global search changes (server mode)
Server-Side Metadata
totalCountnumber-Total number of records (required for server-side pagination)
Feature Toggles
enableRowSelectionbooleanfalseEnable row selection checkboxes
enableGlobalSearchbooleantrueEnable global search input
enableColumnVisibilitybooleantrueEnable column visibility toggle
enableColumnResizingbooleantrueEnable column resizing by dragging
enableDensitySelectorbooleantrueEnable density selector (compact/normal/spacious)
enableCsvExportbooleantrueEnable CSV export button
Virtual Scrolling
enableVirtualScrollbooleanAuto (50+ rows)Enable virtual scrolling for performance
virtualScrollHeightnumber600Max height in pixels for virtual scroll container
virtualScrollOverscannumber10Number of rows to render outside viewport
Pagination
pageSizeOptionsnumber[][10, 20, 50]Available page size options
defaultPageSizenumber10Initial page size
Density
density'compact' | 'normal' | 'spacious''normal'Row height density
State Persistence
storageKeystring-localStorage key for persisting table state
Initial State
initialStateTableInitialState-Initial table state (sorting, filters, pagination, visibility)
External Control
selectedRowsT[]-Externally controlled selected rows (for clearing selection)
Row Actions
rowActions(row: T) => ReactNode-Render function for row action buttons
pinActions'right' | 'none''right'Pin actions column to right side
Row Identification
getRowId(row: T, index: number) => string-Custom row ID function (important for selection)
Styling
classNamestring-Additional CSS classes for container
Custom Export
onExportCsv() => void-Custom CSV export handler (overrides default)
Labels (i18n)
labelsDataTableLabels-Custom labels for internationalization

TableInitialState

ts
interface TableInitialState {
  sorting?: SortingState
  columnFilters?: ColumnFiltersState
  pagination?: { pageIndex: number; pageSize: number }
  columnVisibility?: VisibilityState
}

DataTableLabels

ts
interface DataTableLabels {
  loading?: string          // Default: "Loading..."
  noResults?: string        // Default: "No results found"
  errorMessage?: string     // Default: "Failed to load data"
  actions?: string          // Default: "Actions"
  clearFilters?: string     // Default: "Clear Filters"
  exportCsv?: string        // Default: "Export CSV"
  columns?: string          // Default: "Columns"
  search?: string           // Default: "Search…"
  selectFilter?: string     // Default: "Select…"
}

Column Definition

DataTableColumn<T>

PropertyTypeDescription
idstringRequired. Unique column identifier
headerReactNodeRequired. Column header content (string or component)
cell(row: T) => ReactNodeRequired. Cell render function
accessorKeystringAccessor key for sorting/filtering (defaults to id)
sortablebooleanEnable sorting for this column
sortIdstringServer-side sort field name (defaults to id)
filterFilterConfigColumn filter configuration
visiblebooleanInitial visibility (default: true)
widthnumberInitial width in pixels
minWidthnumberMinimum width in pixels (default: 80)
maxWidthnumberMaximum width in pixels
classNamestringAdditional CSS classes for cells
mobileRender(row: T) => ReactNodeCustom render for mobile card view
exportValue(row: T) => unknownCustom value for CSV export
exportDefaultValueunknownDefault value if exportValue returns null/undefined

FilterConfig

ts
type FilterConfig = 
  | { type: 'text'; placeholder?: string }
  | { type: 'select'; options: Array<{ label: string; value: string }> }

Text Filter:

  • Client mode: Fuzzy search (case-insensitive substring match)
  • Server mode: Debounced search (300ms default)

Select Filter:

  • Exact match filtering
  • Dropdown with predefined options

Type Exports

ts
export type TableMode = 'client' | 'server'
export type TableDensity = 'compact' | 'normal' | 'spacious'

// TanStack Table re-exports
export type {
  SortingState,
  ColumnFiltersState,
  VisibilityState,
  PaginationState,
  RowSelectionState,
} from '@tanstack/react-table'

Example

tsx
import { DataTable, type DataTableColumn } from '@/shared/ui/components/table/DataTable'

type User = {
  id: number
  name: string
  email: string
  role: 'Admin' | 'Manager' | 'Member'
  status: 'Active' | 'Inactive'
}

const columns: DataTableColumn<User>[] = [
  {
    id: 'name',
    header: 'Full Name',
    cell: (row) => <span className="font-medium">{row.name}</span>,
    accessorKey: 'name',
    sortable: true,
    filter: {
      type: 'text',
      placeholder: 'Search names...'
    },
    width: 200,
    minWidth: 150,
  },
  {
    id: 'email',
    header: 'Email Address',
    cell: (row) => row.email,
    sortable: true,
    width: 250,
  },
  {
    id: 'role',
    header: 'Role',
    cell: (row) => row.role,
    filter: {
      type: 'select',
      options: [
        { label: 'Admin', value: 'Admin' },
        { label: 'Manager', value: 'Manager' },
        { label: 'Member', value: 'Member' },
      ]
    },
  },
  {
    id: 'status',
    header: 'Status',
    cell: (row) => (
      <Badge variant={row.status === 'Active' ? 'default' : 'secondary'}>
        {row.status}
      </Badge>
    ),
    filter: {
      type: 'select',
      options: [
        { label: 'Active', value: 'Active' },
        { label: 'Inactive', value: 'Inactive' },
      ]
    },
  },
]

function UsersTable() {
  const [selected, setSelected] = useState<User[]>([])

  return (
    <DataTable
      columns={columns}
      data={users}
      enableRowSelection
      enableGlobalSearch
      enableColumnVisibility
      enableColumnResizing
      enableDensitySelector
      enableCsvExport
      pageSizeOptions={[10, 25, 50]}
      defaultPageSize={25}
      storageKey="users-table-v1"
      density="normal"
      onRowSelectionChange={setSelected}
      selectedRows={selected}
      getRowId={(row) => String(row.id)}
    />
  )
}

SimpleSortableTable

Lightweight table component for simpler use cases.

Import

tsx
import { SimpleSortableTable } from '@/shared/ui/components/table/SimpleSortableTable'
import { type ColumnDef } from '@tanstack/react-table'

Props

SimpleSortableTableProps<T>

PropTypeDefaultDescription
columnsColumnDef<T>[]RequiredTanStack Table column definitions
dataT[]RequiredArray of data objects
initialSortSortingState[]Initial sorting state
density'compact' | 'normal' | 'spacious''normal'Row height density
classNamestring-Additional CSS classes
onRowClick(row: T) => void-Row click handler
selectedRowIdstring-ID of currently selected row (for highlighting)
getRowId(row: T) => string-Custom row ID function
expandablebooleanfalseEnable row expansion
renderExpandedRow(row: T, toggleExpand: () => void) => ReactNode-Render function for expanded content
expandedRowIdsstring[]-Controlled expanded row IDs
onExpandedChange(ids: string[]) => void-Callback when expanded rows change
multiExpandbooleantrueAllow multiple rows to be expanded
defaultExpandedRowIdsstring[][]Initially expanded row IDs
enablePaginationbooleanfalseEnable pagination
defaultPageSizenumber10Default page size
pageSizeOptionsnumber[][5, 10, 20, 50]Page size options

Example

tsx
import { SimpleSortableTable } from '@/shared/ui/components/table/SimpleSortableTable'
import { type ColumnDef } from '@tanstack/react-table'

type Task = {
  id: string
  title: string
  priority: number
  status: string
}

const columns: ColumnDef<Task>[] = [
  {
    accessorKey: 'title',
    header: 'Task Title',
  },
  {
    accessorKey: 'priority',
    header: 'Priority',
    enableSorting: true,
  },
  {
    accessorKey: 'status',
    header: 'Status',
    cell: ({ row }) => (
      <Badge>{row.original.status}</Badge>
    ),
  },
]

function TaskList({ tasks }: { tasks: Task[] }) {
  return (
    <SimpleSortableTable
      columns={columns}
      data={tasks}
      density="normal"
      onRowClick={(task) => navigate(`/tasks/${task.id}`)}
      expandable
      renderExpandedRow={(task) => (
        <div className="p-4">
          <p>Task details for: {task.title}</p>
        </div>
      )}
    />
  )
}

TablePagination

Standalone pagination component used by DataTable.

Import

tsx
import { TablePagination } from '@/shared/ui/components/table/TablePagination'

Props

TablePaginationProps

PropTypeDefaultDescription
pageIndexnumberRequiredCurrent page index (0-based)
pageSizenumberRequiredCurrent page size
totalCountnumber-Total number of items (optional for cursor-based)
pageSizeOptionsnumber[][10, 20, 50, 100]Available page size options
onPageChange(pageIndex: number) => void-Callback when page changes
onPageSizeChange(pageSize: number) => void-Callback when page size changes
canPreviousPagebooleanpageIndex > 0Disable previous button
canNextPagebooleantrueDisable next button
labelsPaginationLabels-Custom labels for i18n
classNamestring-Additional CSS classes

PaginationLabels

ts
interface PaginationLabels {
  rowsPerPage?: string  // Default: "Rows per page"
  page?: string         // Default: "Page"
  of?: string           // Default: "of"
}

Example

tsx
import { TablePagination } from '@/shared/ui/components/table/TablePagination'

function CustomPagination() {
  const [pageIndex, setPageIndex] = useState(0)
  const [pageSize, setPageSize] = useState(10)

  return (
    <TablePagination
      pageIndex={pageIndex}
      pageSize={pageSize}
      totalCount={250}
      pageSizeOptions={[10, 25, 50, 100]}
      onPageChange={setPageIndex}
      onPageSizeChange={(size) => {
        setPageSize(size)
        setPageIndex(0) // Reset to first page
      }}
      labels={{
        rowsPerPage: 'Items per page',
        page: 'Page',
        of: 'of',
      }}
    />
  )
}

EditableTableCell

Inline editable table cell component.

Import

tsx
import { EditableTableCell } from '@/shared/ui/components/table/EditableTableCell'

Props

EditableTableCellProps

PropTypeDefaultDescription
valuestring | numberRequiredCurrent value to display and edit
onSave(value: string | number) => voidRequiredCallback when value is saved
type'text' | 'number''text'Input type
prefixstring-Prefix to display (e.g., "$" for currency)
classNamestring-Additional CSS classes
validate(value: string | number) => boolean-Custom validation function

Built-in Validation

  • Text: Prevents saving empty strings
  • Number: Prevents saving NaN or negative numbers
  • Custom: Use validate prop for additional rules

Example

tsx
import { EditableTableCell } from '@/shared/ui/components/table/EditableTableCell'
import { DataTable, type DataTableColumn } from '@/shared/ui/components/table/DataTable'

type Product = {
  id: number
  name: string
  price: number
  stock: number
}

const columns: DataTableColumn<Product>[] = [
  {
    id: 'name',
    header: 'Product Name',
    cell: (row) => (
      <EditableTableCell
        value={row.name}
        type="text"
        onSave={(newName) => updateProduct(row.id, { name: newName })}
        validate={(value) => String(value).length >= 3}
      />
    ),
  },
  {
    id: 'price',
    header: 'Price',
    cell: (row) => (
      <EditableTableCell
        value={row.price}
        type="number"
        prefix="$"
        onSave={(newPrice) => updateProduct(row.id, { price: newPrice })}
        validate={(value) => Number(value) > 0}
      />
    ),
  },
  {
    id: 'stock',
    header: 'Stock',
    cell: (row) => (
      <EditableTableCell
        value={row.stock}
        type="number"
        onSave={(newStock) => updateProduct(row.id, { stock: newStock })}
      />
    ),
  },
]

function ProductsTable({ products }: { products: Product[] }) {
  return <DataTable columns={columns} data={products} />
}

Type Reference

TanStack Table Types

The DataTable component re-exports commonly used TanStack Table types:

ts
import type {
  SortingState,
  ColumnFiltersState,
  VisibilityState,
  PaginationState,
  RowSelectionState,
  ColumnSizingState,
  Row,
  Table,
  ColumnDef,
} from '@tanstack/react-table'

Sorting State

ts
type SortingState = Array<{
  id: string        // Column ID
  desc: boolean     // true = descending, false = ascending
}>

// Example
const sorting: SortingState = [
  { id: 'name', desc: false },    // Sort by name ascending
  { id: 'createdAt', desc: true }, // Then by date descending
]

Column Filters State

ts
type ColumnFiltersState = Array<{
  id: string        // Column ID
  value: unknown    // Filter value
}>

// Example
const filters: ColumnFiltersState = [
  { id: 'role', value: 'Admin' },
  { id: 'status', value: 'Active' },
]

Pagination State

ts
type PaginationState = {
  pageIndex: number  // 0-based page index
  pageSize: number   // Number of rows per page
}

// Example
const pagination: PaginationState = {
  pageIndex: 2,      // Third page (0-indexed)
  pageSize: 25,      // 25 rows per page
}

Row Selection State

ts
type RowSelectionState = Record<string, boolean>

// Example
const rowSelection: RowSelectionState = {
  '1': true,   // Row with ID '1' is selected
  '5': true,   // Row with ID '5' is selected
  '10': true,  // Row with ID '10' is selected
}

See Also