Skip to content
BigBang

Popular

    ↑↓Navigate↵OpenEscClose
    TR

    Components

    DataTable

    Shows large or changing data in a table with sorting, selection, column visibility and virtualisation.

    Storybook
    Storybook
    Source
    Source
    Package
    @bigbang/ui
    Import
    import { DataTable } from '@bigbang/ui';

    DataTable is in the @bigbang/ui package and is built on TanStack Table (v9) and TanStack Virtual; both come as dependencies of the package. Installation and style files are the same as for Button; see the Button code tab.

    import { createDataTableColumnHelper, DataTable } from '@bigbang/ui';
    type Row = { id: string; name: string; count: number };
    const helper = createDataTableColumnHelper<Row>();
    // Define the columns outside the component, or keep them stable with useMemo.
    const columns = [
    helper.accessor('name', { header: 'Name', meta: { rowHeader: true } }),
    helper.accessor('count', { header: 'Count', meta: { numeric: true } }),
    ];
    <DataTable columns={columns} data={rows} getRowId={(row) => row.id} caption="Item list" />;
    columnsRequired
    Description
    The column definitions (TanStack ColumnDef). Keep the array stable, with useMemo or a module constant. Options for the cell go in meta: align, numeric, truncate, headerLabel, rowHeader.
    Type
    DataTableColumnDef<TRow>[]
    dataRequired
    Description
    The rows to show. Keep the array stable between renders; a new array on every render recomputes the table.
    Type
    TRow[]
    getRowIdRequired
    Description
    Returns a stable unique id for a row, such as its record id. Selection and focus follow this id, so never use the index for data that changes.
    Type
    (row: TRow, index: number) => string
    captionRequired
    Description
    The table's title. It names the table and its scroll region for screen readers.
    Type
    ReactNode
    captionHidden
    Description
    Hides the caption visually and keeps it for assistive technology.
    Type
    boolean
    Default
    false
    sorting
    Description
    Sorting state, [{ id: 'name', desc: false }]. Setting it makes sorting controlled; pair it with onSortingChange.
    Type
    SortingState
    defaultSorting
    Description
    The initial sorting when you do not control it.
    Type
    SortingState
    onSortingChange
    Description
    Called with the new sorting when the user clicks a sortable header.
    Type
    (sorting: SortingState) => void
    manualSorting
    Description
    Sorting happens on the server: the table shows data in the given order and only reports the sorting through onSortingChange.
    Type
    boolean
    Default
    false
    selectionMode
    Description
    Adds a checkbox column. multiple also adds a select-all checkbox that shows a mixed state; single allows one selected row.
    Type
    'none' | 'single' | 'multiple'
    Default
    'none'
    rowSelection
    Description
    Selected rows as { [rowId]: true }. Setting it makes selection controlled; pair it with onRowSelectionChange.
    Type
    RowSelectionState
    defaultRowSelection
    Description
    The initial selection when you do not control it.
    Type
    RowSelectionState
    onRowSelectionChange
    Description
    Called with the new selection when the user toggles a row or the select-all checkbox.
    Type
    (selection: RowSelectionState) => void
    getRowLabel
    Description
    Returns the text that names a row, such as its name. It labels the row checkbox ("Select row Item 1"). Without it the row id is used.
    Type
    (row: TRow) => string
    columnVisibility
    Description
    Column visibility, { [columnId]: false } hides a column. Setting it makes visibility controlled.
    Type
    ColumnVisibilityState
    defaultColumnVisibility
    Description
    The initial visibility when you do not control it.
    Type
    ColumnVisibilityState
    onColumnVisibilityChange
    Description
    Called with the new visibility when a column is shown or hidden.
    Type
    (visibility: ColumnVisibilityState) => void
    columnToggle
    Description
    Shows the built-in column button above the table, a panel of checkboxes that shows or hides columns.
    Type
    boolean
    Default
    false
    toolbar
    Description
    Content at the start of the bar above the table, such as a filter bar or a search field.
    Type
    ReactNode
    density
    Description
    Row height: compact uses 6 px, standard 8 px and comfortable 12 px of block padding in each cell.
    Type
    'compact' | 'standard' | 'comfortable'
    Default
    'standard'
    stickyHeader
    Description
    Keeps the header cells at the top while the body scrolls. Give the scroll container a height with scrollClassName.
    Type
    boolean
    Default
    false
    hoverable
    Description
    Tints a body row on hover with a colour change only.
    Type
    boolean
    Default
    true
    striped
    Description
    Tints every second body row.
    Type
    boolean
    Default
    false
    status
    Description
    What the table shows: ready the rows; loading skeleton rows under the header and aria-busy; empty and filtered-empty a message; error a message with a retry button. A ready table with no rows shows the empty message.
    Type
    'ready' | 'loading' | 'empty' | 'filtered-empty' | 'error'
    Default
    'ready'
    onClearFilters
    Description
    Adds a "Clear filters" button to the filtered-empty message.
    Type
    () => void
    onRetry
    Description
    Adds a "Try again" button to the error message.
    Type
    () => void
    rowActions
    Description
    Renders the actions of a row, such as IconButtons, in a last column that stays at the inline end. Each action is its own tab stop and needs a name.
    Type
    (row: TRow) => ReactNode
    onRowOpen
    Description
    Makes the first column's cell content a button that calls this with the row, so a row is never click-only.
    Type
    (row: TRow) => void
    renderExpanded
    Description
    Content shown in a full-width row under a row when it is expanded, such as installments or refund history. Adds a first column of expand buttons.
    Type
    (row: TRow) => ReactNode
    getRowCanExpand
    Description
    Returns whether a row can expand; rows without details get no button. Without it every row can expand.
    Type
    (row: TRow) => boolean
    expanded
    Description
    Expanded rows as { [rowId]: true }. Setting it makes expansion controlled; pair it with onExpandedChange.
    Type
    Record<string, boolean>
    defaultExpanded
    Description
    The rows expanded on first render when you do not control them.
    Type
    Record<string, boolean>
    onExpandedChange
    Description
    Called with the new expanded rows when the user opens or closes one.
    Type
    (expanded: Record<string, boolean>) => void
    virtualize
    Description
    Renders only the rows in view plus an overscan, with padding rows keeping the scroll height. Use it from about 1,000 rows. It needs a fixed-height scroll container (scrollClassName) and rows of equal height.
    Type
    boolean | { estimateRowHeight?: number; overscan?: number; }
    Default
    false
    totalRowCount
    Description
    Total number of rows when data holds only part of them, such as one server page. It sets aria-rowcount.
    Type
    number
    messages
    Description
    Replaces library texts, such as { empty: 'No items yet' }.
    Type
    Partial<Record<DataTableMessageKey, string>>
    scrollClassName
    Description
    Classes for the scroll container that holds the table, such as max-h-96 for a sticky header or a virtualised list.
    Type
    string
    className
    Description
    For layout only: width and margins of the whole component.
    Type
    string

    columns are TanStack Table v9 column definitions. createDataTableColumnHelper<Row>() wires the types for you. The column meta field takes these options:

    meta Meaning
    align start, center or end alignment.
    numeric Aligns to the end and uses tabular numerals.
    truncate Cuts long text on one line; the column needs a width.
    headerLabel The name of the sort button, the column panel and announcements when the header is not text.
    rowHeader Makes the cells of the column row headers (<th scope="row">).
    const columns = [
    helper.accessor('name', { header: 'Name', meta: { rowHeader: true } }),
    // A custom cell: a StatusBadge from the status vocabulary
    helper.accessor('status', {
    header: 'Status',
    enableSorting: false,
    cell: (context) => <StatusBadge status={context.getValue()} />,
    }),
    // The header is not text: give it a name with headerLabel
    helper.accessor('owner', { header: () => <Icon name="user" />, meta: { headerLabel: 'Owner' } }),
    ];

    enableSorting: false makes a column unsortable; enableHiding: false removes it from the column panel; sortFn and the other TanStack options apply.

    Part Element Props
    DataTable.ColumnToggle <div> and a button columns ({ id, label, visible }), onVisibleChange, label. The part the columnToggle prop uses; you can also use it alone in a custom toolbar.

    DataTable, createDataTableColumnHelper, dataTableStyles and these types: DataTableProps, DataTableColumnDef, DataTableColumnMeta, DataTableMessages, DataTableColumnVisibility, DataTableRowSelection, DataTableSorting.

    • data-component="data-table", data-status: on the outer container.
    • data-part: toolbar, column-toggle, column-toggle-panel, select-header, select-cell, sort, open, actions-header, actions-cell, skeleton-row, state-row, message, spacer, footer, live.
    • The table and row attributes come from Table (data-density, data-selected and so on).
    • data-pin (start, end), and data-pin-edge on the cell at the edge of the pinned area: on pinned cells. data-part: expand-header, expand-cell, expanded-row.
    const [sorting, setSorting] = useState<DataTableSorting>([{ id: 'count', desc: true }]);
    const [selection, setSelection] = useState<DataTableRowSelection>({});
    <DataTable
    columns={columns}
    data={rows}
    getRowId={(row) => row.id}
    caption="Item list"
    sorting={sorting}
    onSortingChange={setSorting}
    selectionMode="multiple"
    rowSelection={selection}
    onRowSelectionChange={setSelection}
    />;
    <DataTable
    columns={columns}
    data={page.rows}
    getRowId={(row) => row.id}
    caption="Item list"
    manualSorting
    sorting={sorting}
    onSortingChange={setSorting}
    totalRowCount={page.total}
    status={isLoading ? 'loading' : isError ? 'error' : 'ready'}
    onRetry={refetch}
    footer={<Pagination … />}
    />
    <DataTable columns={columns} data={rows} getRowId={(row) => row.id} caption="Item list" virtualize scrollClassName="max-h-96" density="compact" />

    virtualize={{ estimateRowHeight: 40, overscan: 12 }} sets the row height and overscan. The default row height is 32 px for compact, 40 px for standard and 48 px for comfortable.

    <DataTable … status="empty" messages={{ empty: 'No items yet' }} />

    messages keys: empty, filtered-empty, clear-filters, error, retry, loading, select-all, select-row, select-column, actions, columns, sorted-asc, sorted-desc, sorted-none, selected-count. The {column}, {row} and {count} placeholders are replaced in the texts that have them.