Data table
Search, sort, select and page through records, built from Table, Checkbox, Input Group, Dropdown Menu, Badge and Empty.
There is no data table component on purpose: every app's data is different. This pattern is the markup and behaviour to copy into your app, as components/<thing>-table.tsx. It uses plain React state, which is plenty for a few hundred rows loaded at once.
| Department | Status | Actions | |||
|---|---|---|---|---|---|
| Chamara Rathnayake | Finance | On leave | 265,000 | ||
| Dilani Fernando | Finance | Active | 320,000 | ||
| Kasun Silva | Operations | Active | 210,000 | ||
| Nimali Perera | Finance | Active | 285,000 | ||
| Ruwan Bandara | Operations | Active | 178,000 |
0 of 7 selected
Page 1 of 2
How it's built
| Part | Built with |
|---|---|
| Search | InputGroup with a search icon and an aria-label |
| Sortable column | A plain <button> in the TableHead, so the label keeps the header's type and lines up with its column; an arrow for the direction, aria-sort on the header |
| Selection | Checkbox per row; the header one is indeterminate when some rows are selected |
| Selected row | data-state="selected" on the TableRow. The theme colors it (brand-soft in Zynactra) |
| Status | Badge success or warning, with a word, never color alone |
| Numbers | font-mono tabular-nums, right-aligned |
| Row actions | One DropdownMenu per row behind an icon button named for the row; destructive last |
| No results | Empty across all columns, saying what wasn't found |
| Paging | Mono page count and outline Previous and Next buttons |
Bigger tables
- Server data. When the server searches and pages, follow the server data table pattern: debounced, cancellable requests, skeleton rows, cursor paging.
- More features (column visibility, resizing, grouping, virtual rows): use TanStack Table for the logic and keep this markup. Version 9 changed the API from v8 (
useTablewith registered features); follow the guides it ships innode_modules/@tanstack/react-table/skills/. - Bulk actions. When rows are selected, show the actions above the table, with the count ("3 selected").
Guidelines
- No brand in a table: selection, sorting and status are state, not the primary action. The page's primary action ("Add employee") sits above the table.
- Wrap the table in
border border-border; don't add a shadow or a card around it. - Five to seven columns. Put the rest in the row's detail view (Sheet).