Loading
Skeleton rows hold the table's height so the page never jumps.
<DataTable
columns={[
{ accessorKey: "name", header: "Name" },
{ accessorKey: "status", header: "Status" },
]}
data={[]}Interactive table — sort, select, expand, and click through rows of data.
import { DataTable } from "@/fragments/ui";Source<DataTable
columns={[
{ accessorKey: "name", header: "Name" },
{ accessorKey: "status", header: "Status" },
]}
data={[npx @usefragments/cli add datatablepnpm add @tanstack/react-tableWrites src/fragments/ui/components/DataTable plus what it imports, the globals stylesheet, and .fragments/registry-lock.json, then prints the packages to add. No account, no key.
Your own registry: publish from Fragments Cloud and add --registry org/name. Connect a workspace.
DataTable is a compound: import the root and reach its parts through dot notation.
DataTable.ColumnsDataTable.preloadSkeleton rows hold the table's height so the page never jumps.
<DataTable
columns={[
{ accessorKey: "name", header: "Name" },
{ accessorKey: "status", header: "Status" },
]}
data={[]}A cell renderer drops any component — avatar, badge — straight into the column.
<DataTable
columns={[
{
accessorKey: "name",
header: "Name",
cell: ({ row }) => (Click a header to sort; click it again to reverse.
<DataTable
columns={[
{ accessorKey: "name", header: "Name" },
{ accessorKey: "amount", header: "Amount" },
]}
data={[The header checkbox toggles every row at once.
<DataTable
columns={[
{ accessorKey: "name", header: "Name" },
{ accessorKey: "status", header: "Status" },
]}
data={[Children fold away under their parent, like a file tree.
<DataTable
columns={[
{ accessorKey: "name", header: "Name" },
{ accessorKey: "type", header: "Type" },
]}
data={[Filter controls sit outside the table; you own the filtering.
<Stack gap="sm">
<Input aria-label="Search users" placeholder="Search..." withFieldWrapper={false} />
<DataTable
columns={[
{ accessorKey: "name", header: "Name" },
{ accessorKey: "status", header: "Status" },Mouse or keyboard opens the row; getRowProps supplies its name.
<DataTable
columns={[
{ accessorKey: "method", header: "Method" },
{ accessorKey: "path", header: "Path" },
]}
data={[{ method: "GET", path: "/v1/components" }]}Row tint alternates so tightly packed rows stay readable.
<DataTable
columns={[
{ accessorKey: "method", header: "Method" },
{ accessorKey: "path", header: "Path" },
]}
data={[emptyMessage replaces the rows and keeps the headers in place.
<DataTable
columns={[
{ accessorKey: "name", header: "Name" },
{ accessorKey: "status", header: "Status" },
]}
data={[]}Oversized values scroll inside the table instead of stretching the page.
<DataTable
columns={[
{ accessorKey: "name", header: "Administrator" },
{ accessorKey: "status", header: "Recovery policy" },
]}
data={[Prop | Type | Default | Description |
|---|---|---|---|
bordered | boolean | Not set | Wrap table in a bordered container |
caption | string | Not set | Visible caption for the table (recommended for accessibility) |
captionHidden | boolean | Not set | Hide the caption visually but keep it for screen readers |
columnsRequired | array | Not set | Column definitions |
dataRequired | array | Not set | Data array |
density | enumcompactregularrelaxedcondensed | Not set | Canonical row density. `condensed` is a deprecated alias for `compact`. |
emptyMessage | string | Not set | Empty state message (plain text). Ignored if `emptyState` is set. |
emptyState | node | Not set | Rich empty-state slot (icon + copy + CTA) rendered when there's no data. |
expanded | union | Not set | Controlled expanded state |
getRowId | function | Not set | Unique key extractor for each row |
getRowProps | function | Not set | Props applied to each rendered data row. Use this for row-level ARIA labels, roles, and data attributes. |
getSubRows | function | Not set | Extract sub-rows from a row for expandable tree tables |
hideHeader | boolean | Not set | Hide the column header row (e.g. stacked per-group tables share one). |
loading | boolean | Not set | When true, render skeleton placeholder rows instead of data. |
onExpandedChange | function | Not set | Expanded state change handler |
onRowClick | function | Not set | Row click handler |
onRowSelectionChange | function | Not set | Selection change handler |
onSortingChange | function | Not set | Sorting change handler |
rowSelection | object | Not set | Controlled selection state |
selectable | boolean | Not set | Enable row selection |
showCheckbox | boolean | Not set | Show checkbox column for row selection |
size | enumsmmd | Not set | — |
skeletonRows | number | Not set | Number of skeleton rows to show while loading (default 6). |
sortable | boolean | Not set | Enable sorting |
sorting | array | Not set | Controlled sorting state |
striped | boolean | Not set | Show alternating row backgrounds |
wrapperClassName | string | Not set | Additional class name for the outer wrapper div |
wrapperProps | object | Not set | Props forwarded to the outer wrapper div |
Do not use DataTable for a simple static comparison.
Don’t
<DataTable />Do
<Table aria-label="Plan comparison">
<Table.Head>
<Table.Row>
<Table.HeaderCell>Plan</Table.HeaderCell>
<Table.HeaderCell>Price</Table.HeaderCell>
</Table.Row>
</Table.Head>
<Table.Body>
<Table.Row>
<Table.Cell>Starter</Table.Cell>
<Table.Cell>$0</Table.Cell>
</Table.Row>
</Table.Body>
</Table>