Skip to main content

DataTable

Interactive table — sort, select, expand, and click through rows of data.

import { DataTable } from "@/fragments/ui";Source

Preview

<DataTable
  columns={[
    { accessorKey: "name", header: "Name" },
    { accessorKey: "status", header: "Status" },
  ]}
  data={[

Installation

npx @usefragments/cli add datatable
pnpm add @tanstack/react-table

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

Anatomy

DataTable is a compound: import the root and reach its parts through dot notation.

  • DataTable.Columns
  • DataTable.preload

Examples

Loading

Skeleton rows hold the table's height so the page never jumps.

<DataTable
  columns={[
    { accessorKey: "name", header: "Name" },
    { accessorKey: "status", header: "Status" },
  ]}
  data={[]}

Rich Cells

A cell renderer drops any component — avatar, badge — straight into the column.

<DataTable
  columns={[
    {
      accessorKey: "name",
      header: "Name",
      cell: ({ row }) => (

Sortable

Click a header to sort; click it again to reverse.

<DataTable
  columns={[
    { accessorKey: "name", header: "Name" },
    { accessorKey: "amount", header: "Amount" },
  ]}
  data={[

Checkbox Selection

The header checkbox toggles every row at once.

<DataTable
  columns={[
    { accessorKey: "name", header: "Name" },
    { accessorKey: "status", header: "Status" },
  ]}
  data={[

Expandable Rows

Children fold away under their parent, like a file tree.

<DataTable
  columns={[
    { accessorKey: "name", header: "Name" },
    { accessorKey: "type", header: "Type" },
  ]}
  data={[

With Filters

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" },

Clickable Rows

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" }]}

Striped

Row tint alternates so tightly packed rows stay readable.

<DataTable
  columns={[
    { accessorKey: "method", header: "Method" },
    { accessorKey: "path", header: "Path" },
  ]}
  data={[

Empty State

emptyMessage replaces the rows and keeps the headers in place.

<DataTable
  columns={[
    { accessorKey: "name", header: "Name" },
    { accessorKey: "status", header: "Status" },
  ]}
  data={[]}

Long Cell Content

Oversized values scroll inside the table instead of stretching the page.

<DataTable
  columns={[
    { accessorKey: "name", header: "Administrator" },
    { accessorKey: "status", header: "Recovery policy" },
  ]}
  data={[

API

Component props
Prop
Type
Default
Description
borderedbooleanNot setWrap table in a bordered container
captionstringNot setVisible caption for the table (recommended for accessibility)
captionHiddenbooleanNot setHide the caption visually but keep it for screen readers
columnsRequiredarrayNot setColumn definitions
dataRequiredarrayNot setData array
densityenumcompactregularrelaxedcondensedNot setCanonical row density. `condensed` is a deprecated alias for `compact`.
emptyMessagestringNot setEmpty state message (plain text). Ignored if `emptyState` is set.
emptyStatenodeNot setRich empty-state slot (icon + copy + CTA) rendered when there's no data.
expandedunionNot setControlled expanded state
getRowIdfunctionNot setUnique key extractor for each row
getRowPropsfunctionNot setProps applied to each rendered data row. Use this for row-level ARIA labels, roles, and data attributes.
getSubRowsfunctionNot setExtract sub-rows from a row for expandable tree tables
hideHeaderbooleanNot setHide the column header row (e.g. stacked per-group tables share one).
loadingbooleanNot setWhen true, render skeleton placeholder rows instead of data.
onExpandedChangefunctionNot setExpanded state change handler
onRowClickfunctionNot setRow click handler
onRowSelectionChangefunctionNot setSelection change handler
onSortingChangefunctionNot setSorting change handler
rowSelectionobjectNot setControlled selection state
selectablebooleanNot setEnable row selection
showCheckboxbooleanNot setShow checkbox column for row selection
sizeenumsmmdNot set
skeletonRowsnumberNot setNumber of skeleton rows to show while loading (default 6).
sortablebooleanNot setEnable sorting
sortingarrayNot setControlled sorting state
stripedbooleanNot setShow alternating row backgrounds
wrapperClassNamestringNot setAdditional class name for the outer wrapper div
wrapperPropsobjectNot setProps forwarded to the outer wrapper div

Accessibility

  • Headers stay real th elements with scope
  • Sortable headers are buttons — reachable by keyboard
  • Selection checkboxes carry their own labels
  • Expand toggles report aria-expanded

Guidance

Use when

  • Rows need sorting, selection, or expansion
  • Users scan and compare several attributes per row
  • A row click opens the record behind it

Avoid when

  • The data is read-only and static (use Table)
  • Each item is a single line (use List)
  • Narrow screens where a card list reads better

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>
  • TablealternativeUse Table for simple semantic HTML tables
  • EmptyStatesiblingUse EmptyState for empty table states
  • BadgesiblingUse Badge for status columns
  • MenusiblingUse Menu for filter dropdowns
  • CheckboxsiblingBuilt-in checkbox selection via showCheckbox

Next steps