Skip to content

API reference

The complete public surface. Every symbol ships full TypeScript types and JSDoc, so editor autocomplete mirrors everything below.

Every adapter (@adapttable/mantine, mui, chakra, antd, unstyled) exports DataTable<TRow>. The props below are the shared core surface (BaseDataTableProps); kit-specific extras follow in Adapter extras.

PropTypeDefaultDescription
sourceTableSource<TRow>Data + state contract from useFrontendData / useBackendData; adapters make it optional when you pass data instead.
rowKey(row: TRow) => stringStable React key extractor for a row (required).
PropTypeDefaultDescription
columnsColumnDef<TRow>[]Column definitions (required) — see ColumnDef.
enableColumnMenubooleanfalseRender the built-in “Columns” menu (show/hide, pin, reorder).
resizableColumnsbooleanfalseEnable drag/keyboard column-resize handles.
columnLayoutColumnLayoutStateControlled column layout (hidden/order/pinned/widths).
onColumnLayoutChange(next: ColumnLayoutState) => voidChange handler for the controlled column layout.
defaultColumnLayoutPartial<ColumnLayoutState>Initial column layout for the uncontrolled mode.
maxHeightnumberFixed-height scroll box (px) enabling sideways scrolling + column pinning; omit for page scroll.
multiSortbooleanfalseShift-click (or shift-Enter) on a header adds the column to the sort chain (asc → desc → removed).
sortByOptionsSortByOption[]Options for a mobile sort-by select.
mobileIdentityColumnsnumber3Leading desktop-visible columns kept on mobile even if hideOnMobile.
PropTypeDefaultDescription
filtersFilterDef<TRow>[] | ReactNodeDeclarative array (the adapter builds the form) or JSX (you draw it); column filter shorthands merge in, a same-key filters entry wins.
filtersMode"popover" | "drawer""popover"Popover anchors a light card under the Filters button (no backdrop); drawer slides in a side panel with one.
filterLabelsRecord<string, ChipLabelResolver>Per-filter-key chip label resolvers (derived automatically by declarative filters).
extraChipsActiveFilterChip[]Extra chips driven by non-URL state, merged with the derived chips.
activeFilterCountnumberchip countOverride the active-filter count badge.
onClearFilters() => voidClear-filters handler used by the panel + chip strip (built-in clearExtras fallback otherwise).
hideSearchbooleanfalseDisable the built-in search box.
searchPlaceholderstringPlaceholder for the search input.
PropTypeDefaultDescription
rowActionsRowAction<TRow>[]Trailing per-row actions (icon buttons on desktop, card buttons on mobile).
bulkActionsBulkAction[]Bulk actions — providing these turns on row selection.
selectionGetId(row: TRow) => stringrowKeySelection id extractor when it must differ from rowKey.
selectedIdsreadonly string[]Controlled selection; apply onSelectionChange requests to your own state.
onSelectionChange(selectedIds: string[]) => voidSelection observer (uncontrolled) or change-request handler (controlled).
confirmConfirmHandlerwindow.confirmConfirmation handler for actions that declare a confirm block.
PropTypeDefaultDescription
tableLabelstringAccessible label for the table.
labelsTableLabelsEnglishPre-translated label overrides; missing keys fall back to English defaults.
dir"ltr" | "rtl""ltr"Text direction.
localestringActive locale tag (e.g. "ar", "ar-EG") driving per-column i18n data-path resolution.
density"comfortable" | "compact""comfortable"Row density; each adapter maps it to its kit’s table size.
isMobilebooleanviewportForce the mobile layout instead of resolving from the viewport.
toolbarReactNodeInline toolbar slot for custom controls (view toggles, export buttons, …).
skeletonRowsnumberpage sizeNumber of skeleton rows while loading.
stickyHeaderbooleanfalseKeep the desktop table header sticky while scrolling.
stickyTopnumber0Sticky toolbar top offset in px (for app headers above the table).
scrollToTopOnChangebooleantrueScroll back to the table when search/filter/page changes.
scrollTopGapnumber8Extra gap below sticky chrome when scrolling back.
rowClassName(row: TRow, index: number) => string | undefinedConditional per-row class, appended on desktop rows and mobile cards alike.
renderRowDetail(row: TRow) => ReactNodeRow expansion: its presence enables the expand chevron; multiple rows may be open, keyed by row id.
summaryRow(rows: readonly TRow[]) => Partial<Record<string, ReactNode>>Map the current page’s rows to per-column footer summary cells.
PropTypeDefaultDescription
virtualizebooleanfalseVirtualize long infinite lists.
estimateRowSizenumber56Desktop row-size estimate in px.
estimateCardSizenumber132Mobile card-size estimate in px.
virtualOverscannumber8Extra rows/cards rendered before and after the virtual window.
virtualScrollMarginnumber0Scroll margin for window virtualization, usually sticky chrome height.

URL props (urlSync, urlKey, urlAdapter, savedViews) and the data / onQueryChange tiers live on the adapter components, not the core prop surface — see Adapter extras and URL-synced state.

PropTypeDefaultDescription
onRowClick(row: TRow) => voidRow activation on click/Enter; interactive children (actions, checkboxes, links) never trigger it.
onRowsChange(rows: readonly TRow[]) => voidCalled whenever the materialized source rows change.
prefetch(row: TRow) => voidHover-prefetch callback fired on desktop row mouse-enter.
PropTypeDefaultDescription
keystringUnique id (required); also the backend sortBy value and — absent accessor/Cell — the row’s dot-path for the cell value.
headerReactNodehumanized keyHeader content; omit it and the header derives from key ("hiredAt" → “Hired At”).
groupstringPresentational header group: contiguous same-group columns render under one spanning header cell.
i18nRecord<string, string>Per-locale data paths for the column’s value ({ key: "nameEn", i18n: { ar: "nameAr" } }); cell, client-side sort and filter follow the resolved path.
filterColumnFilter<TRow>Declarative filter for this column: a bare type ("dateRange") or a definition without key/label.
CellComponentType<CellProps<TRow>>Component rendered per row (receives { row, rowIndex }); define at module level so its identity is stable.
accessor(row: TRow) => ReactNodeLightweight alternative to Cell; returns cell content.
sortValue(row: TRow) => SortableValuePrimitive extractor used by the client-side sort comparator; unused for server-sorted data.
sortablebooleanfalseEnable sorting for this column.
widthnumber | stringColumn width passed through to the rendered header/cell.
align"start" | "center" | "end""start"Text alignment within the cell.
mobileLabelstringheaderLabel used on mobile card layouts; falls back to a string header.
hideOnMobilebooleanfalseHide this column entirely on mobile layouts.
hideOnDesktopbooleanfalseHide this column entirely on desktop layouts.
metaRecord<string, unknown>Arbitrary metadata adapters (or your own code) may read back.
PropTypeDefaultDescription
keystringState key in the filter bag and the f_<key> URL param (required); doubles as the row’s dot-path for the client-side predicate.
typeFilterTypeThe widget shape (required): "text" | "select" | "multiSelect" | "dateRange" | "numberRange".
labelstringhumanized keyWidget + chip label.
optionsFilterOptionsSourceChoices for select/multiSelect: a static FilterOption[], "auto" (distinct frontend values, capped at 50), or an async loader.
getValue(row: TRow) => unknownkey as pathRow-value extractor for the client-side predicate.
placeholderstringPlaceholder for text-like inputs.

Range types persist two inclusive state keys: dateRange${key}From/${key}To, numberRange${key}Min/${key}Max. The range widgets are operator-first (Equal / At least / At most / Between; dates: On / On or after / On or before / Between) — headless: readRangeWidget, writeRangeWidget, RANGE_OPS.

Props beyond the core surface, with per-kit availability.

PropTypeDefaultAvailable onDescription
datareadonly TRow[]allFrontend tier: raw rows the table filters/sorts/pages; with onQueryChange it is the current server page.
totalnumberallServer tier: total row count across all pages (drives the pager).
loadingbooleanallServer tier: a request is in flight.
onQueryChange(query: TableQuery, info: { signal }) => voidallServer tier: fired with the consolidated query whenever it changes (mount included); fetch and hand back data + total.
urlKeystringallNamespace for this table’s URL params (urlKey="left"left.q, left.page, …).
urlAdapterUrlStateAdapterHistory APIallURL-state backend for the data/onQueryChange tiers (router adapter, createMemoryAdapter() in tests).
urlSyncbooleantrueallfalse keeps all state in memory — the address bar never changes, any urlAdapter is ignored.
savedViewsUseSavedViewsOptionsallMounts a saved-views toolbar menu; adapter/urlKey default to the table’s own, so usually only storageKey is needed.
slots{ skeleton?, empty? }allReplace sub-components (loading skeleton, empty state).
classNamesDataTableClassNamesmantine, chakra, unstyledPer-part class overrides — five parts on Mantine/Chakra (root/toolbar/table/card/footer), every part on unstyled.
classNamestringmui, antdClass name applied to the root wrapper.
animatebooleanfalsemantineAnimate rows/cards on mount (dependency-free; honors reduced motion).
sizekit-specific unionmui, chakra, antdExplicit kit table size, overriding the size derived from density (chakra default "md").
colorSchemestringchakraChakra color scheme for primary accents (buttons, badges).
borderedbooleanfalseantdRender the table with cell borders.
virtualHeightnumber480antdVertical scroll height used when virtualize is true.
virtualWidthnumber960antdHorizontal scroll width used when virtualize is true.
emptyStateReactNodeunstyledEmpty-state node override (slots.empty alias wins when both are set).
loadingStateReactNodeunstyledLoading-state node override (slots.skeleton alias wins when both are set).

Each adapter also re-exports the core source builders and types, so one import path covers everything.

All from @adapttable/core.

  • useFrontendData<TRow>(options): TableSource<TRow> — in-memory source: filters, sorts, and slices a raw array from URL state.
  • useBackendData<TRow, TParams, TPage>(options): TableSource<TRow> — wraps your useInfiniteQuery-style hook into the same contract.
  • useServerData<TRow>(options): TableSource<TRow> — hand-rolled-fetch server tier: emits one consolidated TableQuery per change, aborting superseded requests via AbortSignal.
  • useTableData<TRow>(options): { source, runtime } — tier resolution (source ▸ server ▸ frontend) plus the declarative filter runtime; what every adapter calls internally.
  • useTableUrlState(options?): UseTableUrlStateResult — page / limit / search / sort / extra-filter bag in the query string, with setters (setPage, setSearch, setSort, toggleSortLevel, setExtra, setExtras, clearExtras, clearAll).
  • useColumnLayoutUrlState(options?): { layout, onLayoutChange } — URL-persisted column layout (hidden / order / pinned / widths).
  • useColumnLayoutStorageState(options): { layout, onLayoutChange } — the localStorage counterpart (user preference rather than shareable link).
  • useSavedViews(options): { views, save, apply, remove } — named snapshots of this table’s URL params, persisted to storage.
  • createHistoryAdapter() / createMemoryAdapter(initial?) / getHistoryAdapter()UrlStateAdapter.
  • useDataTable<TRow>(options): UseDataTableResult<TRow> — derived state + prop-getters: getTableProps, getHeaderRowProps, getHeaderCellProps, getSortButtonProps, getRowProps, getCellProps, getSearchInputProps.
  • useTableChrome<TRow>(props): TableChrome<TRow> — shared adapter orchestration: layout, confirm, chips, body region (emptyVariant, isRefreshing), clearFilters, footer.
  • useChromeBodyData(chrome, props): ChromeBodyData<TRow> — body data-flow wiring: window virtualization + the infinite-scroll sentinel.
  • useColumnLayout(options): UseColumnLayoutResult<TRow> — headless visibility / order / pinning / width state (visibleColumns, toggleVisible, move, setPinned, setWidth, pinOffset, reset).
  • useSearchInput(...) — debounced search-input state behind getSearchInputProps.
  • useSelection(options): SelectionState — page-scoped selection with select-all and cross-page “all matching”.
  • useRowExpansion(): RowExpansionState — multi-open row expansion keyed by row id.
  • useActiveFilterChips(options) / useExtraChips(options) — removable chips from URL filter state / from non-URL state.
  • useFilterOptions(def): { options, loading } — resolves static, "auto", and async filter-option sources for custom forms.
  • useBulkActionRunner(options): BulkActionRunner — runs bulk actions through the confirm handler.
  • useColumnDragState() — drag-reorder state for custom column menus.
  • useHorizontalOverflow() — scroll-overflow detection for pinned-column affordances.
  • useFilterTriggerToggle() / useChromeScrollReset() — filter-trigger open state / scroll reset on query change.
  • useTableVirtualization(options): TableVirtualization — headless row/card windowing: page scroll by default, element scroll inside a maxHeight box.
  • useInfiniteScroll(options) — IntersectionObserver sentinel ref that auto-loads the next page in infinite mode.
  • useScrollToTableTop(options) — sticky-chrome-aware scroll restoration.
  • useDebounce(value, ms), useMediaQuery(query), useIsMobile(), usePrefersReducedMotion(), useColorScheme(preference).

Notable non-hook helpers: rowsToCsv / downloadCsv (CSV export from your column defs), sortRows / sortRowsMulti / compareValues / nextSort, computePagination, headerGroupRow, columnMenuRows + columnRowDragProps / columnDropProps / columnReorderKeyProps / columnResizeHandleProps (RTL-aware), pinnedCellStyle / edgePinStyle / PIN_Z, tableMinWidth / resolveColumnWidth / parsePxWidth, rowClickProps, resolveFilterDefs / buildFilterRuntime / filterPredicate / materializeAutoOptions / clearedFilterExtras, mergeProps, stableKey, getPath, humanizeKey, resolveLabels / defaultLabels, pageSizeOptions, and the constants DEFAULT_LIMIT (25), PAGE_SIZE_OPTIONS, SEARCH_DEBOUNCE_MS (300), AUTO_OPTIONS_LIMIT (50), ACTIONS_COLUMN_KEY ("actions").

TypeWhat it is
TableSource<TRow>The uniform data + state contract a table consumes (rows, total, loading flags, state read/write).
TableQueryThe consolidated server-tier query: page, limit, search, sortBy, sortDir, sortLevels, filters.
TableQueryParamsBaseline query params a backend list endpoint receives.
PaginatedResponse<TRow>Standard envelope: items, total, page, limit, hasNext.
ColumnLayoutState{ hidden, order, pinned, widths } — the column-layout shape.
TableLabelsEvery string the table renders; all keys optional, English defaults fill gaps.
RowAction<TRow> / BulkActionAction definitions with disabledReason, isHidden, optional confirm wiring.
BulkActionContext{ allMatching, total } — scope handed to a bulk action handler.
ActionConfirm<TArg>Confirmation dialog wiring (title, message, confirmLabel, danger).
ConfirmHandler / ConfirmRequestThe injectable confirmation seam ((request) => void).
ActiveFilterChip / ChipLabelResolverOne removable chip (key, label, onRemove) / value → chip-label function.
UrlStateAdapterThe router seam: getSearch(), setSearch(search, { push? }), subscribe(onChange).
SavedView{ name, search } — one captured view.
FilterDef / FilterType / FilterOption / FilterOptionsSourceThe declarative filter surface (see FilterDef).
CellProps<TRow>{ row, rowIndex } — what a Cell component receives.
SortDirection / SortLevel"asc" | "desc" / one entry in the multi-sort chain.
Direction"ltr" | "rtl".
ColorScheme"light" | "dark" | "auto".
PaginationMode"infinite" | "paged" | "auto" ("auto" resolves by viewport: mobile → infinite).
FilterValue / ExtraFiltersOne URL-round-tripped filter value / the keyed bag of them.
SortableValueComparable primitive returned by a sort-value extractor.
SortByOption{ value, label } for the mobile sort-by select.

Misconfiguration warns once per message in development (silent in production):

  • no data tier, or both source and data/onQueryChange provided;
  • duplicate column keys (sorting, selection, and column layout all target keys);
  • unresolvable sorts (no matching column, or a non-primitive accessor without sortValue);
  • a column filter whose key is also defined in the filters array (the array wins);
  • options: "auto" on a tier with no full dataset, and async options that fail to load;
  • two tables sharing a URL namespace without distinct urlKeys;
  • virtualize combined with renderRowDetail (detail panels are unmeasured sibling rows).
  • @adapttable/i18ngetLabels(locale), getDirection(locale), isRtlLocale(locale), hasLocale(locale), primarySubtag(locale), RTL_LANGUAGES, locales and the ten presets (en, ar, de, es, fr, he, it, ja, pt, zh) — see i18n & RTL.
  • @adapttable/cli — binary adapttable init [--force]; programmatic detectKit, choosePackageManager, installCommand, scaffoldFiles, runInit.