skills/react-table/SKILL.md
Implements data tables using @tanstack/react-table v8 with project UI primitives. Use when adding or modifying tables, column configs, sorting, filtering, row selection, or virtualized table bodies.
npx skillsauth add tianyili/skills react-tableInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This project uses @tanstack/react-table v8 and renders with the project’s Table primitives in @/modules/common/components/ui/table (shadcn-based).
| Layer | Location | Responsibility |
|------|------|------|
| Column config | constants/*TableConfig.tsx | ColumnDef<T>[]: header, accessor, cell, filterFn, size, etc. |
| Container | containers/*Container.tsx | useReactTable, data source, optional virtual/selection/filter |
| Common component | common/components/ui/data-table.tsx | Simple tables can use <DataTable columns={} data={} /> |
| Table UI | common/components/ui/table | Table, TableHeader, TableBody, TableRow / SelectableTableRow, TableHead, TableCell |
ColumnDef<TData>[] from @tanstack/react-table.id: unique identifier (optional; otherwise derived from accessor)header: string or () => ReactNode (use a function when composing UI like sort buttons)accessorKey or accessorFn: value accessorcell: ({ row }) => ReactNode, typically via row.getValue<T>(key) or row.originalsize: number (px). Used for fixed widths and virtualized layoutsfilterFn: custom filter function (see below)enableSorting, sortingFn: sorting controlsExample (simplified):
// constants/exampleTableConfig.tsx
import type { ColumnDef } from '@tanstack/react-table';
export const exampleTableColumns: ColumnDef<ExampleRow>[] = [
{ header: 'Name', accessorKey: 'name', cell: ({ row }) => row.getValue('name') },
{
id: 'amount',
header: 'Amount',
accessorFn: (row) => row.amount,
cell: ({ row }) => <span>{row.original.amount}</span>,
size: 120,
},
];
In a container, call useReactTable with at least data, columns, and getCoreRowModel: getCoreRowModel().
import {
flexRender,
getCoreRowModel,
useReactTable,
} from '@tanstack/react-table';
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
});
Add advanced features only when needed:
getSortedRowModel: getSortedRowModel()getFilteredRowModel: getFilteredRowModel(), optionally filterFns: {} (or a map from filter name to fn)enableRowSelection: true, enableMultiRowSelection: true/false, using row.toggleSelected() and table.getSelectedRowModel().rowsRender headers and cells using the project Table primitives and flexRender.
Header:
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<TableHead key={header.id} style={{ width: header.getSize() }}>
{header.isPlaceholder
? null
: flexRender(header.column.columnDef.header, header.getContext())}
</TableHead>
))}
</TableRow>
))}
</TableHeader>
Body:
<TableBody>
{table.getRowModel().rows.map((row) => (
<TableRow key={row.id} data-state={row.getIsSelected() && 'selected'}>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>
))}
</TableRow>
))}
</TableBody>
For empty states, render a single <TableRow> with <TableCell colSpan={columns.length}>No results.</TableCell>.
DataTableIf you don’t need row selection, virtualization, or custom filters:
import { DataTable } from '@/modules/common/components/ui/data-table';
<DataTable columns={columns} data={data} />
enableRowSelection: true and set enableMultiRowSelection to false (single) or true (multi).SelectableTableRow; call row.toggleSelected() on click; style selected state via data-state={row.getIsSelected() && 'selected'}.table.getIsAllRowsSelected() and table.getToggleAllRowsSelectedHandler().table.getSelectedRowModel().rows.map((row) => row.original).useStableVirtualizer (built on @tanstack/react-virtual), providing count: rows.length, a stable getScrollElement (outer scroll container ref), estimateSize, optional measureElement, and overscan.getScrollElement.rowVirtualizer.getVirtualItems(). Position rows with transform: translateY(${virtualRow.start}px) and set the body container height to rowVirtualizer.getTotalSize().rows.length) changes, a key or state bump may be used to force recalculation (see DiscoverTableContainer / PublicChannelContainer).filterFn)(row, columnId, filterValue, addMeta) => boolean (see Row from @tanstack/react-table).filterFn: customizedXxxFilter on the column definition (e.g. customizedTimeFilter, customizedAddressFilter).table.getColumn(columnId)?.setFilterValue(value) (often driven by filter UI such as time/address dialogs).utils/tableFilters.ts, then import them into column configs.getSortedRowModel: getSortedRowModel().SortButton with onSort={() => column.toggleSorting()} and sortDirection={column.getIsSorted()}.enableSorting: true, sortingFn: 'auto', or a custom sortingFn.constants/<feature>TableConfig.tsx. Export ColumnDef<T>[] or a factory like createXxxTableConfig(...). Export row types as XxxRow / XxxItem.data + columns, call useReactTable, then render with Table primitives + flexRender. Use useRef to hold the table instance or scroll container for virtualization/filter wiring.SelectableTableRow for selectable rows; otherwise TableRow. For virtualization, TableBody often uses display: grid and position: relative, while rows use position: absolute + translateY.constants/*TableConfig.tsx and are typed as ColumnDef<T>[]useReactTable with at least data, columns, and getCoreRowModel()Table / TableHeader / TableBody / TableRow (or SelectableTableRow) and TableHead / TableCell with flexRendergetSortedRowModel() and header UI (project SortButton) where neededgetFilteredRowModel(), set filterFn on columns, and update values via getColumn(id)?.setFilterValue(...)useStableVirtualizer + a stable scroll container)SelectableTableRow + row.toggleSelected() and read selection via getSelectedRowModel()Read individual reference files for detailed code and patterns:
references/README.md
references/minimal-data-table.md
references/row-selection.md
references/sorting-virtualized.md
references/filtering.md
references/table-filters.md
references/multi-select-header.md
references/table-primitives.md
Each reference file contains focused documentation and code examples for that topic. When implementing or modifying tables, load these as needed instead of main-project paths.
development
Use and structure Zustand stores for React and vanilla JS state management. Use when the user mentions Zustand, needs a store pattern, global state, persist state, or migrating from Redux/Context.
tools
Use when displaying token balances or token values in UI, converting user input to bigint for contract writes, or doing math with wei/token amounts in viem or wagmi apps. Web3 number formatting with formatUnits, parseUnits, BigNumber, bigint naming (`Raw`, `Formatted`, `Bn`), decimals handling, and reusable display helpers. Triggers on token balance, formatUnits, parseUnits, wei, decimals, bigint, BigNumber, number formatting, or web3 display math.
development
React performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React code to ensure optimal performance patterns. Triggers on tasks involving React components, data fetching, bundle optimization, or performance improvements.
development
Use when designing or refactoring functions with many optional params, configurable components, or when the user mentions optional params, function signatures, or API simplification. Reduces optional parameters in functions and components for cleaner APIs.