K
@kana-consultant/ui-kit v0.2.0 · docs

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

Full-featured table
Ava Chenava@kana.coadminactive2m ago
Marcus Leemarcus@kana.coeditoractive1h ago
Priya Patelpriya@kana.coadminactiveYesterday
Diego Ramosdiego@kana.coviewerinvited
Kenji Yamamotokenji@kana.coeditoractive3d ago
10 row(s)
Rows per page
Page1of2

Install

pnpm add @kana-consultant/ui-kit @tanstack/react-table

Usage

components/users-table.tsx
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, TableRow
  • TableHead<th> with uppercase tracking
  • TableCell<td> with proper padding
  • TableCaption

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).