Better Tables

BetterTable Props

Complete reference for every prop on the copied <BetterTable /> component.

<BetterTable /> is copied into your app by better-tables init (see UI & CLI) — import it from your local path:

import { BetterTable } from '@/components/better-tables-ui/table/table';

Pass data plus either a table definition (supplies identity and columns) or both id and columns. id alone is not enough — the component throws without columns.

Identity & columns

PropTypeNotes
idstringUnique table instance id (keys the state store and URL params). Defaults to table.tableName when table is given
namestringHuman-readable display name. Defaults to table.tableName
columnsColumnDefinition[]Column definitions. Defaults to table.columns. Server aggregates: t.count / t.aggregate
tableTableDefinitionA defineTable() / tables.define() definition — sugar for columns/id/name (explicit props still win). Enables auto columns resolution when paired with adapter

Data & fetching

PropTypeNotes
dataTData[] (required)The rows to render
adapterTableAdapterOptional — powers lazy filter options, facets, auto-column resolution, and adapter cell-edit saves
totalCountnumberFiltered total for pagination — always pass result.total with server pagination
loadingbooleanRender the loading state
errorError | nullRender the error state
onRetry() => voidRetry button handler for the error state
emptyMessagestringEmpty-state text (wins over emptyState.description)

Initial state

PropType
initialFiltersFilterState[] | FilterGroupNode — a FilterGroupNode tree seeds the initial query, but the filter bar edits flat: the first user edit replaces the tree with a flat implicit-AND array (tree editing is not shipped)
initialSortingSortingState
initialPaginationPaginationState
initialSelectedRowsSet<string>
initialColumnVisibilityColumnVisibility
defaultVisibleColumnsstring[] — ids visible by default; others start hidden

Change callbacks (controlled usage)

PropFires when
onFiltersChange(filters)Filter state changes
onSortingChange(sorting)Sort state changes
onPaginationChange(pagination)Page or page size changes
onPageChange(page)Page changes
onPageSizeChange(pageSize)Page size changes
onSelectionChange(selected)Row selection changes
onRowClick(row)A row is clicked

Typical server-driven wiring: react to the callbacks, refetch via tables.fetchData, pass fresh data + totalCount back in.

Filtering behavior

PropNotes
autoShowFilteredColumnsAuto-reveal a column while it has an active filter (default true). Removing the filter re-hides the column only when defaultVisibleColumns is provided (and the column isn't in it); without that prop, revealed columns stay visible
isFilterProtected(filter)Return true to lock a filter — shown with a lock icon, not removable
groupsManual filter-dropdown grouping (FilterGroup[])
autoGroupFiltersAutomatic grouping config — see Filtering

Editing

PropNotes
editingfalse disables all inline editing
saveActionSerializable server action from tables.cellEditAction(def)
onCellEditFull-control save callback (wins over every other save path)
onCellEditErrorCalled when a save fails (after rollback)

See Inline editing for the save-resolution order.

URL sync

PropNotes
urlSync{ adapter: UrlSyncAdapter, config?: UrlSyncConfig } — the component runs the sync internally; see URL State

Rendering & layout

PropNotes
virtualizedtrue or { height?, rowHeight?, overscan? } — see Large datasets
classNameRoot class name
rowConfiggetId(row) (row identity — required for selection/editing when rows have no id field) and onClick(row) are wired; the remaining RowConfig fields (isSelectable, isExpandable, expandedContent, className, style) are contract-only today — the copied table.tsx doesn't read them yet
emptyState{ description?, icon? } empty-state config (emptyMessage wins for text)
errorStateError-state config
actionsBulk actions on selected rows — see Selection & actions

Feature flags

features toggles whole subsystems:

FlagDefaultEffect
filteringtrueFilter bar + filter dropdowns
sortingtrueHeader sort controls
paginationtruePagination footer
columnVisibilitytrueColumn show/hide menu
rowSelectionfalseCheckbox column + selection state — see Selection & actions
columnReorderingfalseDrag-and-drop header reordering
headerContextMenu—Right-click header menu
<BetterTable columns={columns} data={data} features={{ pagination: false, rowSelection: true }} />

Turning pagination off renders every row — pair with virtualized for big datasets.

Those are the only feature flags. Bulk-action controls appear for selected rows when actions is non-empty and at least one action is visible (isVisible can hide them) — there's no bulkActions flag — and virtualization is the virtualized prop, not a feature flag. Initial filters use the initialFilters prop and the loading state (skeleton rows) uses the loading boolean prop.

On this page