DataTable

Sorting, search and column filters, pagination, checkbox row selection and column visibility on top of Table. useDataTable holds the state; DataTable renders it. No dependencies.

BetaSource
Team members
Email
Ada Lovelaceada@northwind.devOwnerActive12
Grace Hoppergrace@northwind.devAdminActive9
Alan Turingalan@northwind.devMemberActive7
Katherine Johnsonkatherine@northwind.devMemberInvited0
Margaret Hamiltonmargaret@northwind.devAdminActive15

Import

import { DataTable, useDataTable, type DataTableColumn } from "@meridui/react";

Anatomy

const table = useDataTable({ data, columns });

<DataTable table={table} caption="…" />
  • Columns describe each field: accessor (a key or a function) feeds sorting, search and the default cell; cell renders anything else.
  • useDataTable is headless: it returns the current page of rows and every setter. Each piece of state works controlled or uncontrolled.
  • DataTable renders a toolbar (search, Columns menu, your toolbar), the Table with sortable headers and optional checkboxes, and a footer with the status line, a rows-per-page select and Pagination.

Examples

Column filters, default sort and hidden columns

Put your own filter controls in toolbar and drive them with setColumnFilter. A column's filterFn replaces the default "contains" match.

Team members by role
Margaret HamiltonAdminActive15
Ada LovelaceOwnerActive12
Grace HopperAdminActive9
Alan TuringMemberActive7
Barbara LiskovMemberActive5
Frances AllenMemberActive4
Linus TorvaldsViewerActive2
Katherine JohnsonMemberInvited0
Edsger DijkstraViewerInvited0

Headless

Render your own markup from the same state when DataTable's layout does not fit, for example a list of cards on mobile.

const table = useDataTable({ data, columns });

// Everything DataTable renders is available for your own markup:
table.rows;              // current page, filtered and sorted
table.toggleSort("name");
table.setGlobalFilter("ada");
table.setPage(2);
table.toggleRow(table.getRowId(row));
table.selectedRows;      // across pages
table.toggleColumn("email", false);

The hook works on the rows you pass in. For server-side sorting or paging, fetch with your own state and render Table directly.

API reference

DataTableColumn

PropTypeDefaultDescription
idstring–Unique column id.
headerReactNode–Header content.
labelstring–Plain-text name for the Columns menu. Defaults to header when it is a string.
accessorkeyof Row | (row) => unknown–Value for sorting, search and the default cell.
cell(row) => ReactNode–Cell content. Defaults to the accessor value as text.
sortablebooleanfalseAllow sorting by this column.
sortFn(a, b) => number–Custom ascending compare. Defaults to numeric, date and natural text order; empty values last.
searchablebooleantrue with an accessorInclude the column in the global search.
filterFn(row, filter: string) => boolean–Custom per-column filter.
hideablebooleantrueList the column in the Columns menu.
align"start" | "center" | "end""start"Text alignment; end for numbers.

useDataTable

Every state has a controlled prop, a default… prop and an on…Change callback.

PropTypeDefaultDescription
dataRow[]–All rows. Memoise it.
columnsDataTableColumn<Row>[]–Column definitions.
getRowId(row, index) => stringrow.id ?? indexStable id for selection.
sort / defaultSort / onSortChange{ columnId, direction } | null–One sorted column at a time.
globalFilter / defaultGlobalFilter / onGlobalFilterChangestring–Search text; every word must match some searchable column.
columnFilters / defaultColumnFilters / onColumnFiltersChangeRecord<string, string>–Per-column filters.
page / defaultPage / onPageChangenumber1Current page, 1-based.
pageSize / defaultPageSize / onPageSizeChangenumber10Rows per page.
selection / defaultSelection / onSelectionChangestring[]–Selected row ids.
hiddenColumns / defaultHiddenColumns / onHiddenColumnsChangestring[]–Hidden column ids.

It returns rows, filteredRows, visibleColumns, page, pageCount, pageSelection ("all" | "some" | "none"), selectedRows and the setters toggleSort, setGlobalFilter, setColumnFilter, setPage, setPageSize, toggleRow, togglePage, clearSelection and toggleColumn. Changing a filter or the page size returns to page 1.

DataTable

Accepts every Table prop.

PropTypeDefaultDescription
tableDataTableInstance<Row>–State from useDataTable.
captionReactNode–Names the table; visually hidden unless showCaption.
showCaptionbooleanfalseShow the caption above the table.
selectablebooleanfalseAdd a checkbox column.
getRowLabel(row) => string–Names a row in its checkbox label. Defaults to the first visible column.
searchablebooleantrueShow the search box.
columnTogglebooleantrue if any column is hideableShow the Columns menu.
paginatedbooleantrue with more than one pageShow pagination.
pageSizeOptionsnumber[]–Offer a rows-per-page select.
toolbarReactNode–Extra controls in the toolbar.
emptyStateReactNodelabels.emptyShown when no row matches.
labelsPartial<DataTableLabels>–Every visible and screen-reader string; defaults are English.
rootClassNamestring–Class name for the outer wrapper.

DataTableLabels: search, searchPlaceholder, columns, selectPage, selectRow(rowLabel), selected(count, total), results(count), empty, rowsPerPage, pagination, previousPage, nextPage, page(n).

Styling

ClassElement
.mrd-data-tableWrapper
.mrd-data-table__toolbar, .mrd-data-table__search, .mrd-data-table__columnsToolbar parts
.mrd-data-table__selectCheckbox cells
.mrd-data-table__emptyEmpty row cell
.mrd-data-table__footer, .mrd-data-table__status, .mrd-data-table__page-sizeFooter parts

Rows, headers and cells are the Table's own (.mrd-table__*); selected rows get data-selected.

Accessibility

The table keeps native table semantics with a <caption>. Sortable headers are buttons inside <th aria-sort>; every checkbox has a name ("Select Ada Lovelace", "Select all rows on this page") and the header checkbox shows the mixed state. The status line is a polite live region that announces the number of results after a search and the selection count; the search box is described by it.

KeyAction
TabMove through search, Columns, sort buttons, checkboxes and pagination.
EnterSpaceOn a sort button: cycle ascending, descending, unsorted.
SpaceOn a checkbox: select or clear the row (or the page).

Guidelines

Do

Right-align numbers (`align: "end"`) and keep the name column always visible (`hideable: false`).

Avoid

Load thousands of rows into the hook. Page and sort on the server and render Table instead.