A table whose rows expand. A row can hold nested children rows (a tree: departments and the people in them), a details panel from renderDetails (master and detail: a bill and the items on it), or both. Expansion is uncontrolled (defaultExpanded) or controlled (expanded + onExpandedChange); canExpand says which rows can open (by default those with children, or every row when there is renderDetails).

Villains and Minions
NameRole
GruVillain
KevinMinion
StuartMinion

Master and detail. renderDetails shows anything under the row: here it is another NestedTable with nested (no border or scroll box of its own). onExpand is called each time a row opens, so details can load on demand, and loadingKeys puts a spinner on that row's button meanwhile. exclusive keeps one row open at a time, rowActions adds buttons to each row, and expandPosition="end" moves the expand button to a last column (actionsHeader names it). rowKey can be a function and rowLabel names a row for screen readers ("Expand bill B-1042").

Banana orders
BillDate of purchaseItemsTotalMore
B-104212 Mar 20263₹1840
B-105119 Mar 20261₹420
B-106702 Apr 20262₹960

Props

NestedTable

  • columnsNestedTableColumn[]

    Column definitions. See the NestedTableColumn table below.

  • rowsobject[]

    Rows; each row can include nested children.

  • rowKeystring | (row) => string
    Default: 'id'

    Field holding each row’s unique key, or a function returning it.

  • renderDetails(row) => ReactNode

    Content shown under a row when it is expanded (master and detail).

  • canExpand(row) => boolean

    Which rows can expand: by default those with children, or all with renderDetails.

  • defaultExpandedstring[]
    Default: []

    Initially expanded row keys (uncontrolled).

  • expandedstring[]

    Expanded row keys (controlled).

  • onExpandedChange(keys: string[]) => void

    Called when expansion changes.

  • onExpand(row) => void

    Called each time a row opens: load its details here.

  • loadingKeysstring[]
    Default: []

    Rows whose details are loading: their button shows a spinner.

  • exclusiveboolean
    Default: false

    Keep one row open at a time (per level).

  • rowActions(row, open) => ReactNode

    Buttons for each row, in the last column before the expand button.

  • expandPosition'start' | 'end'
    Default: 'start'

    Expand button in the first column, or in a last column.

  • actionsHeaderReactNode
    Default: 'More'

    Header of the last column.

  • rowLabel(row) => string
    Default: the row key

    Names a row in the expand button’s accessible name.

  • nestedboolean
    Default: false

    No border or scroll box: for a table inside another table’s details.

  • emptyReactNode
    Default: 'No data'

    Shown when there are no rows.

  • captionstring

    Screen-reader caption.

  • classNamestring
    Default: ''

    Extra classes for the root element.

NestedTableColumn

  • keystring

    Unique key; also the row field shown when there is no render.

  • headerReactNode

    Column heading.

  • render(row) => ReactNode

    Custom cell content.

  • align'left' | 'center' | 'right'
    Default: 'left'

    Text alignment of the column.