Skip to content

Basics

Loading example…

renderDetailPanel puts a full-width row under the row it belongs to, and an expand column with a chevron appears automatically.

<DataTable
  renderDetailPanel={({ row }) => <OrderLines orderId={row.id} />}
  columns={columns}
  data={orders}
/>

The panel is not rendered until it is opened, so a hundred collapsed rows cost nothing. Pass detailPanelProps.keepMounted when the content is expensive to rebuild and should survive a collapse.

Loading panel content

A panel usually needs data the table never fetched. useDetailPanelData loads it per row and caches it by row id, so re-opening is instant:

function Panel({ row }) {
  const { data, loading, error } = useDetailPanelData(row, () => api.lines(row.id));
  if (loading) return <Spinner />;
  if (error) return <ErrorText error={error} />;
  return <OrderLines lines={data} />;
}

One at a time

expandMode: 'single' collapses the previous panel when another opens, like an accordion. expandOnRowClick makes the whole row the toggle, with the same exclusion for buttons and links that row selection uses. enableExpandAll puts an expand-all toggle in the header.

Rows with children

Sub-rows use the same expansion state and the same toggle. That is a capability of its own; see Tree data.

Customization

The panel is sticky to the left at the container's width, so scrolling a wide table sideways does not drag the panel out of view. detailPanelProps.fullWidth: false opts out and lets the panel scroll with the columns.

The toggle is a slot, and positionExpandColumn moves the column to the other end. The open/close animation is a CSS grid transition that prefers-reduced-motion disables.

Limitations

  • A row has one panel. Two kinds of detail (history and comments) belong in tabs inside the panel, not in two panels.
  • A panel is not a cell. It is a separate row, so it takes no part in sorting, filtering, search or CSV export.
  • The expanded state is keyed by row id, so it resets on refetch unless getRowId is stable and autoResetExpanded is off.

API

  • DataTableProps: enableExpanding, renderDetailPanel, detailPanelProps, expandMode, expandOnRowClick, enableExpandAll, getRowCanExpand, positionExpandColumn, paginateExpandedRows, autoResetExpanded, manualExpanding, onExpandedChange.
  • TableInstance: setExpanded, resetExpanded, toggleAllRowsExpanded, getIsAllRowsExpanded, getExpandedRowModel.
  • Row: toggleExpanded, getIsExpanded, getCanExpand.
  • Hooks: useDetailPanelData.