Primitives
DataTable
Composable data-grid primitives wrapping @tanstack/react-table. Sorting, filtering, pagination, column visibility, and row selection — all themed with kit tokens.
Live example
| Ava Chen | ava@kana.co | admin | active | 2m ago | ||
| Marcus Lee | marcus@kana.co | editor | active | 1h ago | ||
| Priya Patel | priya@kana.co | admin | active | Yesterday | ||
| Diego Ramos | diego@kana.co | viewer | invited | — | ||
| Kenji Yamamoto | kenji@kana.co | editor | active | 3d ago |
10 row(s)
Rows per page
Page1of2
Install
pnpm add @kana-consultant/ui-kit @tanstack/react-table Usage
import {
Table, TableBody, TableCell, TableHead, TableHeader, TableRow,
DataTableColumnHeader, DataTablePagination, DataTableToolbar,
Checkbox, Badge,
} from '@kana-consultant/ui-kit'
import {
useReactTable, getCoreRowModel, getSortedRowModel,
getFilteredRowModel, getPaginationRowModel, flexRender,
type ColumnDef,
} from '@tanstack/react-table'
type TUser = { id: string; name: string; email: string; role: string }
const columns: ColumnDef<TUser>[] = [
{
accessorKey: 'name',
header: ({ column }) => <DataTableColumnHeader column={column} title='Name' />,
cell: ({ row }) => <span className='font-medium'>{row.getValue('name')}</span>,
},
{ accessorKey: 'email', header: 'Email' },
{ accessorKey: 'role', header: 'Role' },
]
export function UsersTable({ data }: { data: TUser[] }) {
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getPaginationRowModel: getPaginationRowModel(),
})
return (
<div className='flex flex-col gap-3'>
<DataTableToolbar table={table} searchColumn='name' />
<Table>
<TableHeader>
{table.getHeaderGroups().map((group) => (
<TableRow key={group.id}>
{group.headers.map((h) => (
<TableHead key={h.id}>
{flexRender(h.column.columnDef.header, h.getContext())}
</TableHead>
))}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows.map((row) => (
<TableRow key={row.id}>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
<DataTablePagination table={table} />
</div>
)
} Building blocks
Table primitives
Table— scroll container + themed<table>TableHeader,TableBody,TableFooter,TableRowTableHead—<th>with uppercase trackingTableCell—<td>with proper paddingTableCaption
DataTable helpers
-
DataTableColumnHeader— sortable header. Props:column,title. Shows a dropdown with ascending / descending / hide options and an icon that reflects the active sort. -
DataTablePagination— full pagination bar. Props:table,pageSizes?,showSelectedCount?. -
DataTableViewOptions— dropdown toggling column visibility. Props:table. -
DataTableToolbar— search input bound to a column + reset filters + actions slot + filters slot + view options. Props:table,searchColumn?,searchPlaceholder?,actions?,filters?,viewOptions?.
Row selection
Add a leading column with a Checkbox in both the header (select-all) and cell
(select-row). See the live demo source for the pattern. Selected rows get
data-state="selected" which the TableRow class styles with a subtle
bg-primary-soft.
Column visibility
Columns are hidable by default. Mark enableHiding: false on the column
definition for columns that should always stay visible (e.g. select / actions columns).