Advanced Table

Column Configuration

Multi-Header Columns


Use a nested columns array in your columnDefinitions to create multiple header rows. Any column with columns is treated as a grouped header, and its child columns are displayed beneath it.

Multi-Header Columns (Multiple Levels)


Multiple levels of column headers can also be rendered as seen here.

Multi-Header Columns with Custom Cells


Multi-Header Columns with Vertical Borders


Column Visibility Control


The columnVisibilityControl prop allows users to toggle the visibility of table columns dynamically.

The default can be enabled simply by passing { default:true } to the prop as shown. This will render the header with the icon enabled dropdown. The dropdown contains all columns present in the Table and any can be toggled on or off via the checkboxes.
NOTE: The first column will not be shown in the dropdown as an option since all the expansion logic/functionality lives there and it should always be visible.

Column Visibility Control With State


The columnVisibilityControl prop also allows for greater control over the columnVisibility state. Devs can manage state themselves by passing in value and onChange as shown.

The additional onColumnVisibilityChange provides a callback with the current state as the argument if needed.

Column Visibility Control with Custom Dropdown


By using the includeIds key/value pair as shown within the columnVisibilityControl prop, you can control which columns show up as options in the columnVisibility dropdown.

Column Visibility Control with Multi-Header Columns


The columnVisibilityControl prop can also be used with multi-header columns as shown.

Grouped headers, custom headers, sort, and pinned rows


Grouped headers, custom UI, sort, and pinned rows

This example combines patterns that often show up together in product tables:

  1. Multi-level headers — nested columns in columnDefinitions.
  2. Custom group header — a header function returning React (here: StarRating, sort icon, PbReactPopover menu). Parent groups are not sort targets; only leaf columns use enableSort: true (see Enable Sort By Column (Multi-Column)).
  3. Programmatic sort — the group header receives TanStack’s table. Call table.setSorting([{ id: "<leafColumnId>", desc: boolean }]) using the same id values as your leaf columns. Match direction icons to the built-in kit (arrow-up-arrow-down unsorted; arrow-up-wide-short / arrow-down-short-wide when sorted).
  4. Pinned row + sticky headerpinnedRows with row ids and tableProps={{ sticky: true }} (see Pinned Rows).

Implementation notes

  • header must be a child component if you need hooks (e.g. popover open state). Render it from header: ({ table }) => <YourHeader table={table} />.
  • Avoid wrapping the primary control in Tooltip — it can steal the first tap/click. Use a title on the button or copy in the doc instead.
  • Popover rows: use a plain <button> as reference, closeOnClick="outside". Picking the same metric again should toggle desc; switching to another leaf column often defaults to desc: true to align with sortDescFirst.
  • Data: advanced_table_grouped_headers_composition_mock_data.json — twelve flat rows (2015–2026) with varied Count / Scheduled / % values so sorting is obvious; id "12" is 2026 and is pinned by default.

Other building blocks on this kit: Custom Header with Multiple Headers, Sticky Header.


Available Props