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

    DataTable is for data that users scan, sort or select: a list of records, an admin screen. The data may arrive page by page, hold hundreds or thousands of rows and change over time.

    • For small, read-only data: use Table. Without interaction the extra weight of DataTable is wasted.
    • For key-value pairs: use DescriptionList.
    • For repeated single-column rows: use ListItem.
    • For editing in cells: DataTable is read-only; use a form or a separate view to edit.
    • When you need grid navigation (cell by cell with arrow keys): DataTable does not provide it; each interactive cell is its own tab stop.
    Table DataTable
    Data Small, read-only, ready on the page Large, fetched or changing
    Sorting, selection No Yes
    Column visibility No Yes
    Loading, empty, error Built by hand Built in (status)
    Virtualisation No virtualize
    Parts Table.* The same Table.* parts
    1. Toolbar: the toolbar content and the column button; optional.
    2. Scroll region: the named, focusable container (from Table).
    3. Header: the selection column, the column headers (a button when sortable) and the actions column.
    4. Body: the data rows; messages in the loading, empty and error states.
    5. Actions column: rowActions; sticky at the end of the row.
    6. Footer: footer; for pagination.
    7. Live region: the hidden area that announces sorting and selection changes.
    • Sorting: the header button cycles three states: ascending, descending, unsorted. One column is sorted at a time.
    • Selection: aria-selected is not valid on a plain table; a selected row shows data-selected and the checked state of its checkbox. The selected count is announced in a polite live region.
    • Column visibility: the panel stays in the page flow; Escape closes it and returns focus to the button.
    • Row actions: the actions column stays at the end of the row while the table scrolls sideways.
    • States: while loading the header stays and the body is five skeleton rows. The error message has role="alert".
    • Virtualisation: only the visible rows plus an overscan are rendered; empty padding rows above and below keep the scroll height. Rows must be of equal height.
    • No row animation: rows update without animation when the data changes; tables do not animate rows.
    • No arrow-key navigation: interactive cells are reached with Tab.
    • Pinned columns (meta.pin) stay in place while the table scrolls sideways; their offsets come from the measured widths of the pinned columns.
    • In expandable rows the expand button opens and closes the detail row, which spans every column. An open row stays open by its id when the page or sort changes.

    When the data is small and read-only, Table is enough; choose DataTable only when you need sorting, selection or loading states.

    Item list
    NameCount
    Item 112
    DoTable for a short read-only list.
    Item list
    Item 112
    Don'tDataTable for one row with no sorting or selection: unnecessary.

    The name of a row action should say which row it belongs to; screen readers read buttons as a list.

    Item list
    İşlemler
    Item 112
    Item 286
    DoThe name includes the row: "Edit: Item 1".
    Item list
    İşlemler
    Item 112
    Item 286
    Don'tThe same name in every row ("Edit"): it is unclear which row.

    Do not leave the table blank when there is no data; say what happened and give a way out when you can.

    Item list

    Filtrelere uyan kayıt yok

    DoA message and an action in the empty state.
    Item list
    NameCount
    Don'tBlank after the header: it is unclear whether there is no data or it is loading.
    • Keep column headers short and in sentence case: “Created”, “Owner”. Do not force upper case.
    • Write the caption as a noun phrase: “Item list”.
    • Let getRowLabel return the text that best identifies the row: its name or title. The id is a last resort.
    • Keep empty and error messages short and say what to do: “Try again”, “Clear filters”.
    • Put the row in the name of action buttons: “Edit: Item 1”.
    • Turn on virtualize from about 1,000 rows. Without it, thousands of rows raise interaction latency (INP); the target is an INP under 200 ms.
    • Keep the columns and data arrays stable (useMemo or a module constant). Passing a new array on every render recomputes the table.
    • Sort and paginate very large data on the server (manualSorting, totalRowCount).
    • With virtualisation the row height must be fixed; cell content must not wrap to a second line. Pass estimateRowHeight when needed.