DataTable
stableA full-featured data grid with a rich column definition API, tree data, copy/paste, density, bulk actions, row action menus, custom slots, search, nested filters, virtualization, pinning, grouping, aggregation and more.
Basic usage
Name | Email | Role | Team | Status | Revenue | Cost | Score | Row total | Actions | |
|---|---|---|---|---|---|---|---|---|---|---|
Ada Lovelace | ada@example.com | Admin | Platform | Active | 1,800 | 920 | 91 | 2720 | ||
Grace Hopper | grace@example.com | Admin | Growth | Active | 2,100 | 990 | 88 | 3090 | ||
Katherine Johnson | katherine@example.com | Owner | Support | Invited | 1,500 | 760 | 82 | 2260 | ||
| Total | 5400 | 890 | 91 |
Examples
Search, filters and pagination
Global search, column filter state, nested AND/OR filters, selection and pagination can run locally or be mirrored to a server adapter.
Project | Owner | Status | Budget | Revenue | Cost | Progress | |
|---|---|---|---|---|---|---|---|
Workspace 1 | Ada Lovelace | Healthy | $12k | 1,500 | 700 | 35 | |
Workspace 5 | Ada Lovelace | Healthy | $24k | 1,980 | 1,000 | 63 | |
Workspace 6 | Grace Hopper | Review | $27k | 2,100 | 1,075 | 70 | |
Workspace 7 | Margaret Hamilton | Blocked | $30k | 2,220 | 1,150 | 77 | |
Workspace 8 | Alan Turing | Queued | $33k | 2,340 | 1,225 | 84 | |
Workspace 9 | Ada Lovelace | Healthy | $36k | 2,460 | 1,300 | 91 | |
Workspace 13 | Ada Lovelace | Healthy | $48k | 2,940 | 1,600 | 59 | |
Workspace 15 | Margaret Hamilton | Blocked | $54k | 3,180 | 1,750 | 73 |
Virtual rows and columns
Use row and column virtualization together for unlimited-feeling datasets without rendering every cell.
Project | Owner | Status | Budget | Revenue | Cost | Progress | M1 | M2 | M3 | M4 | M5 | M6 | M7 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Workspace 1 | Ada Lovelace | Healthy | $12k | 1,500 | 700 | 20 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
Workspace 2 | Grace Hopper | Review | $15k | 1,533 | 719 | 31 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
Workspace 3 | Margaret Hamilton | Blocked | $18k | 1,566 | 738 | 42 | 42 | 43 | 44 | 45 | 46 | 47 | 48 |
Workspace 4 | Alan Turing | Queued | $21k | 1,599 | 757 | 53 | 53 | 54 | 55 | 56 | 57 | 58 | 59 |
Workspace 5 | Ada Lovelace | Healthy | $24k | 1,632 | 776 | 64 | 64 | 65 | 66 | 67 | 68 | 69 | 70 |
Workspace 6 | Grace Hopper | Review | $27k | 1,665 | 795 | 75 | 75 | 76 | 77 | 78 | 79 | 80 | 81 |
Workspace 7 | Margaret Hamilton | Blocked | $30k | 1,698 | 814 | 86 | 86 | 87 | 88 | 89 | 90 | 91 | 92 |
Workspace 8 | Alan Turing | Queued | $33k | 1,731 | 833 | 97 | 97 | 98 | 99 | 100 | 101 | 102 | 103 |
Workspace 9 | Ada Lovelace | Healthy | $36k | 1,764 | 852 | 28 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
Workspace 10 | Grace Hopper | Review | $39k | 1,797 | 871 | 39 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
Workspace 11 | Margaret Hamilton | Blocked | $42k | 1,830 | 890 | 50 | 50 | 51 | 52 | 53 | 54 | 55 | 56 |
Workspace 12 | Alan Turing | Queued | $45k | 1,863 | 909 | 61 | 61 | 62 | 63 | 64 | 65 | 66 | 67 |
Configuration, pinning and actions
Column configuration, column selection, row pinning, column pinning, grouping, row actions and detail panels are built in.
Project | Owner | Status | Budget | Revenue | Cost | Progress | Actions | |
|---|---|---|---|---|---|---|---|---|
Workspace 1 | Ada Lovelace | Healthy | $12k | 1,500 | 700 | 35 | ||
Workspace 2 | Grace Hopper | Review | $15k | 1,620 | 775 | 42 | ||
Workspace 3 | Margaret Hamilton | Blocked | $18k | 1,740 | 850 | 49 | ||
Workspace 4 | Alan Turing | Queued | $21k | 1,860 | 925 | 56 | ||
Workspace 5 | Ada Lovelace | Healthy | $24k | 1,980 | 1,000 | 63 | ||
Workspace 6 | Grace Hopper | Review | $27k | 2,100 | 1,075 | 70 | ||
Workspace 7 | Margaret Hamilton | Blocked | $30k | 2,220 | 1,150 | 77 | ||
Workspace 8 | Alan Turing | Queued | $33k | 2,340 | 1,225 | 84 | ||
Workspace 9 | Ada Lovelace | Healthy | $36k | 2,460 | 1,300 | 91 | ||
Workspace 10 | Grace Hopper | Review | $39k | 2,580 | 1,375 | 38 | ||
Workspace 11 | Margaret Hamilton | Blocked | $42k | 2,700 | 1,450 | 45 | ||
Workspace 12 | Alan Turing | Queued | $45k | 2,820 | 1,525 | 52 | ||
Workspace 13 | Ada Lovelace | Healthy | $48k | 2,940 | 1,600 | 59 | ||
Workspace 14 | Grace Hopper | Review | $51k | 3,060 | 1,675 | 66 | ||
Workspace 15 | Margaret Hamilton | Blocked | $54k | 3,180 | 1,750 | 73 | ||
Workspace 16 | Alan Turing | Queued | $57k | 3,300 | 1,825 | 80 | ||
Workspace 17 | Ada Lovelace | Healthy | $60k | 3,420 | 1,900 | 87 | ||
Workspace 18 | Grace Hopper | Review | $63k | 3,540 | 1,975 | 94 | ||
Workspace 19 | Margaret Hamilton | Blocked | $66k | 3,660 | 2,050 | 41 | ||
Workspace 20 | Alan Turing | Queued | $69k | 3,780 | 2,125 | 48 | ||
Workspace 21 | Ada Lovelace | Healthy | $72k | 3,900 | 2,200 | 55 | ||
Workspace 22 | Grace Hopper | Review | $75k | 4,020 | 2,275 | 62 | ||
Workspace 23 | Margaret Hamilton | Blocked | $78k | 4,140 | 2,350 | 69 | ||
Workspace 24 | Alan Turing | Queued | $81k | 4,260 | 2,425 | 76 |
Totals, spanning and row configuration
Footer aggregations, row totals, cell colSpan/rowSpan and row-level classes cover analytical grids.
Project | Owner | Status | Budget | Revenue | Cost | Progress | Row total |
|---|---|---|---|---|---|---|---|
Workspace 1 | Ada Lovelace | Healthy | $12k | 1,500 | 700 | 35 | 2200 |
Workspace 2 | Grace Hopper | Review | $15k | 1,620 | 775 | 42 | 2395 |
Workspace 3 | Blocked | $18k | 1,740 | 850 | 49 | 2590 | |
Workspace 4 | Alan Turing | Queued | $21k | 1,860 | 925 | 56 | 2785 |
Workspace 5 | Ada Lovelace | Healthy | $24k | 1,980 | 1,000 | 63 | 2980 |
Workspace 6 | Grace Hopper | Review | $27k | 2,100 | 1,075 | 70 | 3175 |
Workspace 7 | Blocked | $30k | 2,220 | 1,150 | 77 | 3370 | |
Workspace 8 | Alan Turing | Queued | $33k | 2,340 | 1,225 | 84 | 3565 |
Workspace 9 | Ada Lovelace | Healthy | $36k | 2,460 | 1,300 | 91 | 3760 |
Workspace 10 | Grace Hopper | Review | $39k | 2,580 | 1,375 | 38 | 3955 |
Workspace 11 | Blocked | $42k | 2,700 | 1,450 | 45 | 4150 | |
Workspace 12 | Alan Turing | Queued | $45k | 2,820 | 1,525 | 52 | 4345 |
Workspace 13 | Ada Lovelace | Healthy | $48k | 2,940 | 1,600 | 59 | 4540 |
Workspace 14 | Grace Hopper | Review | $51k | 3,060 | 1,675 | 66 | 4735 |
Workspace 15 | Blocked | $54k | 3,180 | 1,750 | 73 | 4930 | |
Workspace 16 | Alan Turing | Queued | $57k | 3,300 | 1,825 | 80 | 5125 |
Workspace 17 | Ada Lovelace | Healthy | $60k | 3,420 | 1,900 | 87 | 5320 |
Workspace 18 | Grace Hopper | Review | $63k | 3,540 | 1,975 | 94 | 5515 |
Workspace 19 | Blocked | $66k | 3,660 | 2,050 | 41 | 5710 | |
Workspace 20 | Alan Turing | Queued | $69k | 3,780 | 2,125 | 48 | 5905 |
Workspace 21 | Ada Lovelace | Healthy | $72k | 3,900 | 2,200 | 55 | 6100 |
Workspace 22 | Grace Hopper | Review | $75k | 4,020 | 2,275 | 62 | 6295 |
Workspace 23 | Blocked | $78k | 4,140 | 2,350 | 69 | 6490 | |
Workspace 24 | Alan Turing | Queued | $81k | 4,260 | 2,425 | 76 | 6685 |
| Total | 69120 | 1562.5 | 94 | ||||
Inline add, lazy loading and localization
Inline create rows, scroll-end lazy loading, skeleton/spinner/text loaders and localized labels are all prop-driven.
Project | Owner | Status | Budget | Revenue | Cost | Progress |
|---|---|---|---|---|---|---|
Workspace 1 | Ada Lovelace | Healthy | $12k | 1,500 | 700 | 35 |
Workspace 2 | Grace Hopper | Review | $15k | 1,620 | 775 | 42 |
Workspace 3 | Margaret Hamilton | Blocked | $18k | 1,740 | 850 | 49 |
Workspace 4 | Alan Turing | Queued | $21k | 1,860 | 925 | 56 |
Workspace 5 | Ada Lovelace | Healthy | $24k | 1,980 | 1,000 | 63 |
Workspace 6 | Grace Hopper | Review | $27k | 2,100 | 1,075 | 70 |
Workspace 7 | Margaret Hamilton | Blocked | $30k | 2,220 | 1,150 | 77 |
Workspace 8 | Alan Turing | Queued | $33k | 2,340 | 1,225 | 84 |
Workspace 9 | Ada Lovelace | Healthy | $36k | 2,460 | 1,300 | 91 |
Workspace 10 | Grace Hopper | Review | $39k | 2,580 | 1,375 | 38 |
| Cargando mas... | ||||||
Column Definition API
DataTableColumnDef extends TanStack ColumnDef with field, headerName, type, align, flex, renderCell, renderHeader, description and filterOperators.
Full Nameℹ | Email | Role | Revenue | Scoreℹ | Joined |
|---|---|---|---|---|---|
User 1 | user1@example.com | Admin | $1,200 | 40 | Jan 1, 2026 |
User 2 | user2@example.com | Editor | $1,280 | 47 | Feb 2, 2026 |
User 3 | user3@example.com | Viewer | $1,360 | 54 | Mar 3, 2026 |
User 4 | user4@example.com | Admin | $1,440 | 61 | Apr 4, 2026 |
User 5 | user5@example.com | Editor | $1,520 | 68 | May 5, 2026 |
User 6 | user6@example.com | Viewer | $1,600 | 75 | Jun 6, 2026 |
User 7 | user7@example.com | Admin | $1,680 | 82 | Jul 7, 2026 |
User 8 | user8@example.com | Editor | $1,760 | 89 | Aug 8, 2026 |
User 9 | user9@example.com | Viewer | $1,840 | 96 | Sep 9, 2026 |
User 10 | user10@example.com | Admin | $1,920 | 43 | Oct 10, 2026 |
User 11 | user11@example.com | Editor | $2,000 | 50 | Nov 11, 2026 |
User 12 | user12@example.com | Viewer | $2,080 | 57 | Dec 12, 2026 |
Tree data
Set treeData and provide getSubRows to render a parent/child hierarchy with automatic depth indentation. Expand All and Collapse All appear in the toolbar.
Name | Type | Membersℹ |
|---|---|---|
Engineering | Department | 42 |
Design | Department | 14 |
Growth | Department | 20 |
Column management
Resize columns by dragging the edge handle (double-click to auto-fit). Drag headers to reorder. Pin any column left or right via the ⋮ menu. Lock a column to prevent resize, reorder, and hide. Toggle visibility with the Columns button. Below: column groups created by nesting columns under a parent definition.
Resize: drag the ▕ handle at column edges. Double-click a handle to auto-fit. Reorder: drag column headers. Pin: open column ⋮ menu → Pin left / right. Lock: locked columns (currently: Name) cannot be resized, reordered, or hidden.
Name | Email | Role | Revenue | Score | Joined |
|---|---|---|---|---|---|
User 1 | user1@example.com | Admin | 1,200 | 40 | Jan 1, 2026 |
User 2 | user2@example.com | Editor | 1,280 | 47 | Feb 2, 2026 |
User 3 | user3@example.com | Viewer | 1,360 | 54 | Mar 3, 2026 |
User 4 | user4@example.com | Admin | 1,440 | 61 | Apr 4, 2026 |
User 5 | user5@example.com | Editor | 1,520 | 68 | May 5, 2026 |
User 6 | user6@example.com | Viewer | 1,600 | 75 | Jun 6, 2026 |
User 7 | user7@example.com | Admin | 1,680 | 82 | Jul 7, 2026 |
User 8 | user8@example.com | Editor | 1,760 | 89 | Aug 8, 2026 |
Column groups — nested columns under a shared header:
| Identity | Performance | |||
|---|---|---|---|---|
Name | Role | Score | Revenue | Joined |
User 1 | Admin | 40 | 1,200 | Jan 1, 2026 |
User 2 | Editor | 47 | 1,280 | Feb 2, 2026 |
User 3 | Viewer | 54 | 1,360 | Mar 3, 2026 |
User 4 | Admin | 61 | 1,440 | Apr 4, 2026 |
User 5 | Editor | 68 | 1,520 | May 5, 2026 |
User 6 | Viewer | 75 | 1,600 | Jun 6, 2026 |
Row management
Drag the ⠿ grip to reorder rows — the sorted array is emitted via onRowOrderChange. Pin rows to top or bottom via the grip menu. Use enableRowCopy / enableColumnCopy to add copy options in the row and column context menus.
Reorder rows: drag the ⠿ grip on the left. Pin rows: open the row grip menu → Pin top / bottom. Copy: use row ⋮ menu to copy a single row, or column ⋮ menu to copy all column values.
Name | Email | Role | Revenue | Score | Joined |
|---|---|---|---|---|---|
User 1 | user1@example.com | Admin | 1,200 | 40 | Jan 1, 2026 |
User 2 | user2@example.com | Editor | 1,280 | 47 | Feb 2, 2026 |
User 3 | user3@example.com | Viewer | 1,360 | 54 | Mar 3, 2026 |
User 4 | user4@example.com | Admin | 1,440 | 61 | Apr 4, 2026 |
User 5 | user5@example.com | Editor | 1,520 | 68 | May 5, 2026 |
User 6 | user6@example.com | Viewer | 1,600 | 75 | Jun 6, 2026 |
User 7 | user7@example.com | Admin | 1,680 | 82 | Jul 7, 2026 |
User 8 | user8@example.com | Editor | 1,760 | 89 | Aug 8, 2026 |
Row actions
rowActionMenu renders a ⋮ dropdown per row (supports separators, disabled/hidden guards, destructive variants). rowActionButtons renders inline buttons. bulkActions shows a panel when rows are selected. loadingRowIds dims individual rows during async mutations. onRowContextMenu / onCellContextMenu handle right-click events.
⋮ menu: per-row dropdown with Edit and Delete. Save button: inline button that triggers a 1.5 s loading state on that row. Bulk: select rows to show the bulk-action bar. Right-click any row or cell for a context menu.
Name | Email | Role | Revenue | Score | Joined | Actions | Actions | |
|---|---|---|---|---|---|---|---|---|
User 1 | user1@example.com | Admin | 1,200 | 40 | Jan 1, 2026 | |||
User 2 | user2@example.com | Editor | 1,280 | 47 | Feb 2, 2026 | |||
User 3 | user3@example.com | Viewer | 1,360 | 54 | Mar 3, 2026 | |||
User 4 | user4@example.com | Admin | 1,440 | 61 | Apr 4, 2026 | |||
User 5 | user5@example.com | Editor | 1,520 | 68 | May 5, 2026 | |||
User 6 | user6@example.com | Viewer | 1,600 | 75 | Jun 6, 2026 | |||
User 7 | user7@example.com | Admin | 1,680 | 82 | Jul 7, 2026 | |||
User 8 | user8@example.com | Editor | 1,760 | 89 | Aug 8, 2026 |
Toolbar features
enableDensityToggle adds a Density menu (compact / standard / comfortable). enableExport adds a dropdown with CSV, JSON and XLSX. enableFullscreen expands the table to fill the viewport. onPrint adds a Print button. onRefresh adds a Refresh button. enableStatusBar pins a count bar below the table.
Density toggle · Export dropdown (CSV / JSON / XLSX) · Fullscreen · Print · Refresh — all in the toolbar. Status bar is pinned below.
Name | Email | Role | Revenue | Score | Joined | |
|---|---|---|---|---|---|---|
User 1 | user1@example.com | Admin | 1,200 | 40 | Jan 1, 2026 | |
User 2 | user2@example.com | Editor | 1,280 | 47 | Feb 2, 2026 | |
User 3 | user3@example.com | Viewer | 1,360 | 54 | Mar 3, 2026 | |
User 4 | user4@example.com | Admin | 1,440 | 61 | Apr 4, 2026 | |
User 5 | user5@example.com | Editor | 1,520 | 68 | May 5, 2026 | |
User 6 | user6@example.com | Viewer | 1,600 | 75 | Jun 6, 2026 | |
User 7 | user7@example.com | Admin | 1,680 | 82 | Jul 7, 2026 | |
User 8 | user8@example.com | Editor | 1,760 | 89 | Aug 8, 2026 | |
User 9 | user9@example.com | Viewer | 1,840 | 96 | Sep 9, 2026 | |
User 10 | user10@example.com | Admin | 1,920 | 43 | Oct 10, 2026 | |
User 11 | user11@example.com | Editor | 2,000 | 50 | Nov 11, 2026 | |
User 12 | user12@example.com | Viewer | 2,080 | 57 | Dec 12, 2026 |
Sorting and filtering options
Hold Shift while clicking column headers to build a multi-column sort chain — numbered priority badges appear on each active sort icon. quickFilterColumns renders a search input below specified headers. enableFilterChips shows active filters as removable chips above the table.
Multi-sort: hold Shift and click column headers — numbered badges show sort priority. Quick filters: type in the input below each header. Filter chips: active filters appear as removable chips.
Name | Email | Role | Revenue | Score | Joined |
|---|---|---|---|---|---|
User 1 | user1@example.com | Admin | 1,200 | 40 | Jan 1, 2026 |
User 2 | user2@example.com | Editor | 1,280 | 47 | Feb 2, 2026 |
User 3 | user3@example.com | Viewer | 1,360 | 54 | Mar 3, 2026 |
User 4 | user4@example.com | Admin | 1,440 | 61 | Apr 4, 2026 |
User 5 | user5@example.com | Editor | 1,520 | 68 | May 5, 2026 |
User 6 | user6@example.com | Viewer | 1,600 | 75 | Jun 6, 2026 |
User 7 | user7@example.com | Admin | 1,680 | 82 | Jul 7, 2026 |
User 8 | user8@example.com | Editor | 1,760 | 89 | Aug 8, 2026 |
User 9 | user9@example.com | Viewer | 1,840 | 96 | Sep 9, 2026 |
User 10 | user10@example.com | Admin | 1,920 | 43 | Oct 10, 2026 |
User 11 | user11@example.com | Editor | 2,000 | 50 | Nov 11, 2026 |
User 12 | user12@example.com | Viewer | 2,080 | 57 | Dec 12, 2026 |
Pagination and status bar
The pagination bar includes a page-number dropdown, rows-per-page selector, total row count, and icon navigation. enableStatusBar adds a compact bar below showing total and selected row counts.
Name | Email | Role | Revenue | Score | Joined | |
|---|---|---|---|---|---|---|
User 1 | user1@example.com | Admin | 1,200 | 40 | Jan 1, 2026 | |
User 2 | user2@example.com | Editor | 1,280 | 47 | Feb 2, 2026 | |
User 3 | user3@example.com | Viewer | 1,360 | 54 | Mar 3, 2026 | |
User 4 | user4@example.com | Admin | 1,440 | 61 | Apr 4, 2026 | |
User 5 | user5@example.com | Editor | 1,520 | 68 | May 5, 2026 |
Row appearance
striped alternates row backgrounds. enableRowNumbers adds a fixed row-number column. getRowStatus colors the left border stripe per row. rowHeight sets a uniform or per-row pixel height. enableCellTooltip shows the raw value on hover. getCellClassName applies Tailwind classes to individual cells by value.
# | Name | Email | Role | Revenue | Score | Joined |
|---|---|---|---|---|---|---|
1 | User 1 | user1@example.com | Admin | 1,200 | 40 | Jan 1, 2026 |
2 | User 2 | user2@example.com | Editor | 1,280 | 47 | Feb 2, 2026 |
3 | User 3 | user3@example.com | Viewer | 1,360 | 54 | Mar 3, 2026 |
4 | User 4 | user4@example.com | Admin | 1,440 | 61 | Apr 4, 2026 |
5 | User 5 | user5@example.com | Editor | 1,520 | 68 | May 5, 2026 |
6 | User 6 | user6@example.com | Viewer | 1,600 | 75 | Jun 6, 2026 |
7 | User 7 | user7@example.com | Admin | 1,680 | 82 | Jul 7, 2026 |
8 | User 8 | user8@example.com | Editor | 1,760 | 89 | Aug 8, 2026 |
9 | User 9 | user9@example.com | Viewer | 1,840 | 96 | Sep 9, 2026 |
10 | User 10 | user10@example.com | Admin | 1,920 | 43 | Oct 10, 2026 |
Inline editing
Mark columns editable: true and provide valueSetter to write changes back. editMode controls whether a single click or double-click starts editing. enableUndoRedo adds Ctrl+Z / Ctrl+Y. enableValidation + displayValidate on column defs shows a red outline and error tooltip on invalid cells. dirtyRows tracks unsaved row IDs.
Double-click Name or Score to edit inline. Ctrl+Z / Ctrl+Y to undo/redo. Score must be 0–100 (red outline + tooltip on invalid). Dirty rows are tracked.
Name | Score | Role | Revenue |
|---|---|---|---|
User 1 | 40 | Admin | 1,200 |
User 2 | 47 | Editor | 1,280 |
User 3 | 54 | Viewer | 1,360 |
User 4 | 61 | Admin | 1,440 |
User 5 | 68 | Editor | 1,520 |
User 6 | 75 | Viewer | 1,600 |
User 7 | 82 | Admin | 1,680 |
User 8 | 89 | Editor | 1,760 |
Clipboard and cell selection
enableCopyPaste lets users press Ctrl+C to copy selected rows as TSV — paste directly into Excel or Google Sheets. enablePaste enables Ctrl+V to paste TSV back into editable cells. enableCellSelection adds click-drag or Shift+click rectangular range selection.
Ctrl+C copies selected rows as TSV (paste into Excel / Sheets). Click-drag or Shift+click to select a cell range.
Name | Email | Role | Revenue | Score | Joined | |
|---|---|---|---|---|---|---|
User 1 | user1@example.com | Admin | 1,200 | 40 | Jan 1, 2026 | |
User 2 | user2@example.com | Editor | 1,280 | 47 | Feb 2, 2026 | |
User 3 | user3@example.com | Viewer | 1,360 | 54 | Mar 3, 2026 | |
User 4 | user4@example.com | Admin | 1,440 | 61 | Apr 4, 2026 | |
User 5 | user5@example.com | Editor | 1,520 | 68 | May 5, 2026 | |
User 6 | user6@example.com | Viewer | 1,600 | 75 | Jun 6, 2026 | |
User 7 | user7@example.com | Admin | 1,680 | 82 | Jul 7, 2026 | |
User 8 | user8@example.com | Editor | 1,760 | 89 | Aug 8, 2026 |
Conditional formatting
Set enableConditionalFormatting to add a Format button in the toolbar. Users open a drawer to create rules that highlight cells by column value — choose operator, value, background and text color. Rules are serializable and can be stored externally via conditionalFormattingRules + onConditionalFormattingRulesChange.
Name | Role | Score | Revenue |
|---|---|---|---|
User 1 | Admin | 40 | 1,200 |
User 2 | Editor | 47 | 1,280 |
User 3 | Viewer | 54 | 1,360 |
User 4 | Admin | 61 | 1,440 |
User 5 | Editor | 68 | 1,520 |
User 6 | Viewer | 75 | 1,600 |
User 7 | Admin | 82 | 1,680 |
User 8 | Editor | 89 | 1,760 |
User 9 | Viewer | 96 | 1,840 |
User 10 | Admin | 43 | 1,920 |
User 11 | Editor | 50 | 2,000 |
User 12 | Viewer | 57 | 2,080 |
Built-in cell renderers and formatting
Set type on a column to get rich built-in cell rendering: badge (with badgeMap for color mapping), currency (Intl.NumberFormat), progress bar, star rating, link, avatar. Add locale / dateFormat / numberFormat / timezone per column for Intl-based formatting of date and number columns.
Name | Status | Revenue | Score | Rating | Joined |
|---|---|---|---|---|---|
Alice | Active | $1,200.00 | 20% | January 1, 2022 | |
Bob | Paused | $1,540.00 | 30% | February 4, 2022 | |
Carol | Blocked | $1,880.00 | 40% | March 7, 2022 | |
Dave | Invited | $2,220.00 | 50% | April 10, 2022 | |
Eve | Active | $2,560.00 | 60% | May 13, 2022 | |
Frank | Paused | $2,900.00 | 70% | June 16, 2022 | |
Grace | Blocked | $3,240.00 | 80% | July 19, 2022 | |
Heidi | Invited | $3,580.00 | 90% | August 22, 2022 |
Analytics features
enableToolPanel adds a collapsible right-side panel with Columns, Filters, and Stats tabs. enableHeaderStats pins an aggregated stats row below column headers (count / sum / avg / min / max / unique — configurable per column via headerStatsConfig). enableSavedViews adds a drawer to save, load, update and delete named table states.
Tool panel: open the ▶ button on the right to access Columns, Filters, and Stats tabs. Saved views: toolbar button to save and restore named table states. Header stats: sum/avg/count row pinned below column headers.
Name | Email | Role | Revenue | Score | Joined | |
|---|---|---|---|---|---|---|
count12 | count12 | count12 | count12 | sum19,680 | avg63.5 | count12 |
User 1 | user1@example.com | Admin | 1,200 | 40 | Jan 1, 2026 | |
User 2 | user2@example.com | Editor | 1,280 | 47 | Feb 2, 2026 | |
User 3 | user3@example.com | Viewer | 1,360 | 54 | Mar 3, 2026 | |
User 4 | user4@example.com | Admin | 1,440 | 61 | Apr 4, 2026 | |
User 5 | user5@example.com | Editor | 1,520 | 68 | May 5, 2026 | |
User 6 | user6@example.com | Viewer | 1,600 | 75 | Jun 6, 2026 | |
User 7 | user7@example.com | Admin | 1,680 | 82 | Jul 7, 2026 | |
User 8 | user8@example.com | Editor | 1,760 | 89 | Aug 8, 2026 | |
User 9 | user9@example.com | Viewer | 1,840 | 96 | Sep 9, 2026 | |
User 10 | user10@example.com | Admin | 1,920 | 43 | Oct 10, 2026 | |
User 11 | user11@example.com | Editor | 2,000 | 50 | Nov 11, 2026 | |
User 12 | user12@example.com | Viewer | 2,080 | 57 | Dec 12, 2026 |
Live data
Set enableLiveData to watch for data prop changes and flash updated cells with a highlight animation. Pair with liveDataKey (default: "id") as the row identity key. Useful for dashboards with WebSocket or polling data sources.
Name | Email | Role | Revenue | Score | Joined |
|---|---|---|---|---|---|
User 1 | user1@example.com | Admin | 1,200 | 40 | Jan 1, 2026 |
User 2 | user2@example.com | Editor | 1,280 | 47 | Feb 2, 2026 |
User 3 | user3@example.com | Viewer | 1,360 | 54 | Mar 3, 2026 |
User 4 | user4@example.com | Admin | 1,440 | 61 | Apr 4, 2026 |
User 5 | user5@example.com | Editor | 1,520 | 68 | May 5, 2026 |
User 6 | user6@example.com | Viewer | 1,600 | 75 | Jun 6, 2026 |
Async detail panel
loadDetailPanel receives a Row and returns a Promise<ReactNode>. The resolved content is displayed in an expandable panel below the row. Panels are LRU-cached (detailPanelCacheSize, default 20) so re-expanding does not re-fetch.
Click ▶ to expand a row — panel loads async then caches.
Name | Email | Role | Revenue | Score | Joined |
|---|---|---|---|---|---|
User 1 | user1@example.com | Admin | 1,200 | 40 | Jan 1, 2026 |
User 2 | user2@example.com | Editor | 1,280 | 47 | Feb 2, 2026 |
User 3 | user3@example.com | Viewer | 1,360 | 54 | Mar 3, 2026 |
User 4 | user4@example.com | Admin | 1,440 | 61 | Apr 4, 2026 |
User 5 | user5@example.com | Editor | 1,520 | 68 | May 5, 2026 |
User 6 | user6@example.com | Viewer | 1,600 | 75 | Jun 6, 2026 |
Pivot mode
Set enablePivot to add a Pivot toolbar button. Clicking it opens a configuration drawer where you choose the row group field, pivot field, value field and aggregation function. The table re-renders as a cross-tabulation view. Pass pivotConfig + onPivotConfigChange for controlled state.
30 rows across 4 regions, 3 products, 3 categories and 4 quarters. Click the Pivot button in the toolbar to open the configuration drawer and choose row group, pivot field, value field and aggregation.
Region | Product | Category | Quarter | Rep | Sales | Cost | Units | Margin % |
|---|---|---|---|---|---|---|---|---|
North | Widget A | Hardware | Q1 | Alice | 12,400 | 7,200 | 80 | 42 |
North | Widget B | Software | Q1 | Bob | 8,800 | 2,900 | 55 | 67 |
North | Widget C | Services | Q1 | Carol | 6,100 | 4,200 | 31 | 31 |
South | Widget A | Hardware | Q1 | Dave | 9,500 | 5,600 | 63 | 41 |
South | Widget B | Software | Q1 | Eve | 11,200 | 3,700 | 70 | 67 |
East | Widget A | Hardware | Q1 | Frank | 7,800 | 4,500 | 52 | 42 |
East | Widget C | Services | Q1 | Grace | 5,200 | 3,600 | 26 | 31 |
West | Widget B | Software | Q1 | Hank | 9,900 | 3,200 | 62 | 68 |
West | Widget A | Hardware | Q1 | Ivy | 14,100 | 8,200 | 94 | 42 |
North | Widget B | Software | Q2 | Alice | 13,000 | 4,300 | 82 | 67 |
North | Widget A | Hardware | Q2 | Bob | 15,500 | 9,100 | 103 | 41 |
South | Widget C | Services | Q2 | Carol | 7,300 | 5,000 | 37 | 32 |
South | Widget A | Hardware | Q2 | Dave | 10,800 | 6,300 | 72 | 42 |
East | Widget B | Software | Q2 | Eve | 6,200 | 2,100 | 39 | 66 |
East | Widget A | Hardware | Q2 | Frank | 13,500 | 7,900 | 90 | 41 |
State persistence
Pass a unique stateKey to automatically save and restore sort, filter, column visibility, column sizing, column order, pagination and density to localStorage. Refresh the page — the table state is fully restored.
Sort, filter, resize, and paginate — then refresh the page. State is restored from localStorage automatically.
Name | Email | Role | Revenue | Score | Joined |
|---|---|---|---|---|---|
User 1 | user1@example.com | Admin | 1,200 | 40 | Jan 1, 2026 |
User 2 | user2@example.com | Editor | 1,280 | 47 | Feb 2, 2026 |
User 3 | user3@example.com | Viewer | 1,360 | 54 | Mar 3, 2026 |
User 4 | user4@example.com | Admin | 1,440 | 61 | Apr 4, 2026 |
User 5 | user5@example.com | Editor | 1,520 | 68 | May 5, 2026 |
Mobile card view
Set mobileBreakpoint to "sm", "md", or "lg". Below that breakpoint the table switches to a label/value card list — one card per row, one item per column. Resize the browser window to see the transition.
Resize the browser to below the md breakpoint to see the card view.
Custom empty states
NoRowsOverlay renders when the data source is empty. NoResultsOverlay renders when filters/search produce zero matches from a non-empty dataset. Both accept any ReactNode — render illustrations, calls to action, or upload prompts.
Name | Email | Role | Revenue | Score | Joined |
|---|---|---|---|---|---|
No users yet. Create the first one. | |||||
Features
- Rich DataTableColumnDef API — field, type, align, flex, renderCell, description, filterOperators.
- Tree data with depth indentation and Expand All / Collapse All toolbar buttons.
- Ctrl+C copy/paste to TSV for Excel and Google Sheets.
- Density toggle — compact, standard, comfortable cell padding.
- Bulk actions panel when rows are selected; row action menu and inline button columns.
- Pagination with page-number dropdown, rows-per-page selector and total row count.
- Row copy and column copy via row/column menus.
- Full slot system — replace toolbar, pagination, column menu, filter, search, loaders, empty states.
- Distinct empty states: NoRowsOverlay (empty source) vs NoResultsOverlay (filtered empty).
- Sorting, global search, nested AND/OR filters, selection, resizing, pinning and reordering.
- Virtualized rows and columns for large datasets with lazy loading.
- Column configuration, aggregation totals, inline create, detail panels and localization.
- Server-side state adapter, skeleton/spinner/text loaders and accessibility built in.
Installation
pnpm dlx structyl add data-tableAPI Reference
DataTable
A typed, batteries-included data grid with MUI-like feature coverage on top of TanStack Table.
| Prop | Type | Default |
|---|---|---|
| columns | DataTableColumn<TData>[]Column definitions for the dataset. | — |
| data | TData[]Rows to render. | — |
| virtual | boolean | { estimatedRowHeight?: number; overscan?: number }Render rows with virtualization. | — |
| virtualColumns | boolean | { estimatedColumnWidth?: number; overscan?: number }Render visible leaf columns with horizontal virtualization for wide grids. | — |
| enableSorting | booleanEnable sortable column headers. | true |
| enableFiltering | booleanEnable column filtering state. | false |
| enableAdvancedFiltering | booleanRender the nested AND/OR filter builder. | false |
| enableGlobalSearch | booleanRender a global quick-search input. | false |
| enableRowSelection | boolean | 'single'Enable row selection checkboxes. | false |
| enableColumnSelection | booleanTrack selected columns from the column menu/configuration panel. | false |
| enablePagination | booleanRender pagination controls. | false |
| enableExpanding | booleanEnable expandable rows or tree rows when sub-rows are provided. | false |
| enableGrouping | booleanEnable row grouping from column menus. | false |
| enableColumnResizing | booleanAllow resizing columns. | false |
| enableColumnReordering | booleanAllow reordering columns. | false |
| enableRowReordering | booleanAllow drag-and-drop row reordering. | false |
| enableColumnPinning | booleanAllow pinning columns. | false |
| enableRowPinning | booleanAllow rows to be pinned to top or bottom. | false |
| enableColumnConfiguration | booleanRender the column visibility/configuration panel. | false |
| pageSize | numberInitial rows per page. | 10 |
| loading | booleanShow the loading state. | — |
| loadingMore | booleanShow a lazy-loading row at the bottom. | — |
| loadingVariant | 'text' | 'skeleton' | 'spinner'Choose text, skeleton, or spinner loading UI. | 'text' |
| skeletonRows | numberRows to render for the skeleton loading state. | 5 |
| error | ReactNodeRender an error state. | — |
| emptyState | ReactNodeRender custom empty content. | — |
| globalFilter | stringControlled global search value. | — |
| defaultGlobalFilter | stringUncontrolled initial global search value. | — |
| onGlobalFilterChange | (value: string) => voidCalled when the global search changes. | — |
| advancedFilter | DataTableFilterGroupControlled nested filter model. | — |
| defaultAdvancedFilter | DataTableFilterGroupUncontrolled initial nested filter model. | — |
| onAdvancedFilterChange | (filter?: DataTableFilterGroup) => voidCalled when the filter builder changes. | — |
| rowActions | (row: Row<TData>) => ReactNodeAdds an actions column at the end of the grid. | — |
| inlineCreateRow | DataTableInlineCreateRenders inline add-row fields above the data rows. | — |
| aggregations | Record<string, 'sum' | 'avg' | 'min' | 'max' | 'count' | fn>Column aggregation functions for footer totals. | — |
| rowTotals | boolean | DataTableRowTotals<TData>Adds a row total column calculated from selected columns. | — |
| rowPinning | DataTableRowPinningStateControlled top/bottom row pinning state. | — |
| renderDetailPanel | (row: Row<TData>) => ReactNodeRenders a master/detail panel below expanded rows. | — |
| getCellColSpan | (cell, row) => number | undefinedReturns a cell column span. | — |
| getCellRowSpan | (cell, row) => number | undefinedReturns a cell row span. | — |
| getRowClassName | (row) => string | undefinedAdds row-level classes for row configuration. | — |
| getRowStyle | (row) => CSSProperties | undefinedAdds row-level inline styles. | — |
| getRowHeight | (row) => number | undefinedCustom row height, used by row virtualization. | — |
| height | number | stringFixed grid body height. | — |
| maxHeight | number | stringMaximum grid body height. | — |
| fullHeight | booleanFill the parent height. | — |
| autoHeight | booleanLet content determine the body height. | — |
| onLoadMore | () => voidCalled near the bottom for lazy loading. | — |
| hasMore | booleanWhether lazy loading can request more rows. | — |
| onRowOrderChange | (rows, rowIds) => voidCalled after drag-and-drop row reorder. | — |
| onColumnOrderChange | (columnIds) => voidCalled after drag-and-drop column reorder. | — |
| localeText | Partial<DataTableLocaleText>Localizes built-in labels, buttons, and state text. | — |
| serverSide | { state; onStateChange; rowCount }External state adapter for remote data. | — |
| tableRef | MutableRefObject<Table<TData> | null>Imperative access to the TanStack Table instance. | — |
| className | stringAdditional Tailwind classes, merged with the component defaults. | — |
DataTableToolbar
Optional toolbar for search and actions.
| Prop | Type | Default |
|---|---|---|
| table | Table<TData>TanStack Table instance. | — |
DataTableAdvancedFilter
Nested AND/OR filter builder.
| Prop | Type | Default |
|---|---|---|
| table | Table<TData>TanStack Table instance. | — |
DataTableColumnConfiguration
Column visibility, pinning, grouping, and selection menu.
| Prop | Type | Default |
|---|---|---|
| table | Table<TData>TanStack Table instance. | — |
DataTableColumnVisibility
Column visibility menu alias.
| Prop | Type | Default |
|---|---|---|
| table | Table<TData>TanStack Table instance. | — |