Components
Data table
Table + @tanstack/react-table. Sorting, filtering, and pagination out of the box. Define columns once, pass rows, get a sortable, paged table.
When to usewhen the surface is fundamentally rows — anything with more than ~30 items where the operator wants to sort or scan.
Import
import { DataTable, SortableHeader } from "@ravnhq/efni/data-table"
import type { ColumnDef } from "@tanstack/react-table"Mission ops table
| Status | |||
|---|---|---|---|
| MB-4472 | NANora Adell | in flight | |
| MB-4468 | RCRavi Chandra | queued | |
| MB-4451 | JPJules Park | completed | |
| MB-4432 | IMIris Molinari | aborted | |
| MB-4421 | KOKito Odum | in flight | |
| MB-4415 | SVSena Voss | completed |
Page 1 of 2
const columns: ColumnDef<Mission>[] = [
{
accessorKey: "id",
header: ({ column }) => <SortableHeader column={column}>ID</SortableHeader>,
cell: ({ row }) => <span className="font-mono">{row.getValue("id")}</span>,
},
{ accessorKey: "operator", header: "Operator" },
{ accessorKey: "status", header: "Status" },
{
accessorKey: "progress",
header: "Progress",
cell: ({ row }) => <Progress value={row.getValue("progress")} />,
},
]
<DataTable columns={columns} data={MISSIONS} pageSize={6} />Guidelines
Do
- Use SortableHeader on every column the operator would think to sort by.
- Render IDs, timestamps, and numeric columns with font-mono + tabular-nums.
- Show status as a Badge, not a colored cell — the badge takes color; the row stays scannable.
Don't
- Don't paginate client-side past a few hundred rows — swap in server-side pagination.
- Don't nest interactive controls (button-in-row) unless there's a clear affordance — reach for Context menu instead.
- Don't stripe zebra rows in dense tables; borders are enough.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
columns | ColumnDef<TData, TValue>[] | — | Column defs from @tanstack/react-table — accessorKey, header, cell. |
data | TData[] | — | The rows to render. |
paginated | boolean | true | Enable client-side pagination. Defaults to true. |
pageSize | number | 10 | Rows per page when paginated. |
emptyMessage | React.ReactNode | "No results." | Shown when data is empty. |
className | string | — |