TableOptions

The configuration object passed to createTable() or useTable().

Required

OptionTypeDescription
dataTData[]The data array to display
columnsColumnDef<TData, any>[]Column definitions

State Management

OptionTypeDescription
statePartial<TableState>Controlled state (merged with internal state)
onStateChangeOnChangeFn<TableState>Called when any state changes
initialStatePartial<TableState>Initial state values

Row Identity

OptionTypeDefaultDescription
getRowId(row, index, parent?) => stringString(index)Custom row ID generator

Sorting Options

OptionTypeDefaultDescription
enableSortingbooleantrueEnable sorting globally
enableMultiSortbooleantrueAllow multi-column sorting
enableSortingRemovalbooleantrueAllow removing sort on third click
maxMultiSortColCountnumberInfinityMax simultaneous sort columns
manualSortingbooleanfalseDisable client-side sorting (for server-side)
sortingFnsRecord<string, SortingFn>--Additional named sorting functions
onSortingChangeOnChangeFn<SortingState>--Sorting state change callback
postSortRows(rows) => Row[] | void--Reorder the final sorted rows before render (AG-parity)
isMultiSortEvent(e) => booleanShift keyMulti-sort modifier key test

Filtering Options

OptionTypeDefaultDescription
enableFiltersbooleantrueEnable all filtering
enableColumnFiltersbooleantrueEnable per-column filters
enableGlobalFilterbooleantrueEnable global search
manualFilteringbooleanfalseDisable client-side filtering
filterFnsRecord<string, FilterFn>--Additional named filter functions
globalFilterFnFilterFnOption--Custom global filter function
onColumnFiltersChangeOnChangeFn<ColumnFiltersState>--Column filters change callback
onGlobalFilterChangeOnChangeFn<string>--Global filter change callback
getColumnCanGlobalFilter(column) => boolean--Per-column global filter opt-out

Pagination Options

OptionTypeDefaultDescription
manualPaginationbooleanfalseDisable client-side pagination
pageCountnumber--Total page count (server-side)
rowCountnumber--Total row count (server-side)
autoResetPageIndexbooleantrueReset to page 0 on data change
onPaginationChangeOnChangeFn<PaginationState>--Pagination change callback

Server State

Server-backed tables use the same columns and table components as local tables. The difference is where row-model work happens: local mode lets Yable sort/filter/page in memory; server mode controls those state slices and fetches data from your API.

const table = useTable({
  data: rows,
  columns,
  state: { sorting, columnFilters, globalFilter, pagination },
  onSortingChange: setSorting,
  onColumnFiltersChange: setColumnFilters,
  onGlobalFilterChange: setGlobalFilter,
  onPaginationChange: setPagination,
  manualSorting: true,
  manualFiltering: true,
  manualPagination: true,
  rowCount,
})

React users can use the higher-level useServerTable controller for cursor loading, infinite scroll, and optimistic row updates:

const serverTable = useServerTable({
  columns,
  getRowId: (row) => row.id,
  fetchData: async ({ sorting, globalFilter, cursor, signal }) => {
    const result = await api.accounts.list({ sorting, q: globalFilter, cursor, signal })
    return {
      rows: result.rows,
      cursor: result.nextCursor,
      hasMore: result.hasMore,
      rowCount: result.total,
    }
  },
  updateRow: async ({ rowId, patch, signal }) => {
    return api.accounts.update(rowId, patch, { signal })
  },
})

return <Table table={serverTable.table} />
APIDescription
useServerTable().tableNormal Yable table instance configured for manual server state
useServerTable().rowsCurrent loaded server window
useServerTable().refresh()Replace the loaded window using current sorting/filtering/pagination state
useServerTable().loadMore()Append the next cursor/page for infinite-scroll flows
useServerTable().updateRow()Optimistically patch a row, call the server, then merge or roll back result

Selection Options

OptionTypeDefaultDescription
enableRowSelectionboolean | (row) => booleantrueEnable row selection
enableMultiRowSelectionboolean | (row) => booleantrueAllow selecting multiple rows
enableSubRowSelectionboolean | (row) => booleantrueAuto-select sub-rows
onRowSelectionChangeOnChangeFn<RowSelectionState>--Selection change callback

Visibility Options

OptionTypeDefaultDescription
enableHidingbooleantrueEnable column visibility toggling
onColumnVisibilityChangeOnChangeFn<VisibilityState>--Visibility change callback

Column Ordering

OptionTypeDescription
onColumnOrderChangeOnChangeFn<ColumnOrderState>Column order change callback

Column Pinning

OptionTypeDefaultDescription
enableColumnPinningboolean--Enable column pinning
onColumnPinningChangeOnChangeFn<ColumnPinningState>--Pinning change callback

Column Sizing

OptionTypeDefaultDescription
enableColumnResizingbooleantrueEnable column drag-to-resize
columnResizeMode'onChange' | 'onEnd''onChange'When to update widths
columnResizeDirection'ltr' | 'rtl''ltr'Resize direction
onColumnSizingChangeOnChangeFn<ColumnSizingState>--Sizing change callback
onColumnSizingInfoChangeOnChangeFn<ColumnSizingInfoState>--Resize info change callback

Use column definition sizing options (size, minSize, maxSize, enableResizing) or defaultColumnDef to configure column widths. The React renderer keeps header and body widths synchronized internally, including during horizontal scroll, so consumers should not need custom CSS width overrides or manual <colgroup> synchronization.

Configuration Profiles

React exports a layered config API for site-wide defaults, named table profiles, and reusable named cell configs.

import { YableProvider, createYableConfig, useTable, Table } from '@zvndev/yable-react'

const yableConfig = createYableConfig({
  table: { theme: 'midnight', striped: true, stickyHeader: true },
  columns: {
    default: { size: 160, minSize: 80, maxSize: 420, enableResizing: true },
  },
  rows: { className: 'row-comfortable' },
  cells: {
    named: {
      RichItem: {
        cellStyle: { whiteSpace: 'normal', lineHeight: 1.35, fontWeight: 600 },
      },
    },
  },
  profiles: {
    compactVariant: {
      table: { theme: 'compact', compact: true, stickyHeader: false },
      columns: { default: { size: 112, minSize: 56 } },
      rows: { className: 'row-compact' },
    },
  },
})

function App() {
  return (
    <YableProvider config={yableConfig}>
      <OrdersTable />
    </YableProvider>
  )
}

function OrdersTable() {
  const table = useTable({
    data,
    columns: [columnHelper.accessor('name', { header: 'Name', cellConfig: 'RichItem' })],
    configProfile: 'compactVariant',
  })

  return <Table table={table} configProfile="compactVariant" />
}

Precedence is intentionally local-friendly: global defaults are lowest, named profiles sit above them, table defaultColumnDef sits above profile defaults, named cellConfig is applied per column, and explicit column definition fields or explicit <Table> props always win. Use a provider for site-wide consistency, named profiles for reusable variants, and inline column config for one-off cells.

Selection APIs

Row selection lives in table.getState().rowSelection. Use onRowSelectionChange for controlled state, table.events.on('selection:change', handler) for event-style subscriptions, and table.getSelectedRowModel() when you need the current selected rows.

const table = useTable({
  data,
  columns,
  enableRowClickSelection: true,
  enableCellSelection: true,
  onRowSelectionChange: setRowSelection,
  state: { rowSelection },
})

table.events.on('selection:change', ({ selection, selectedRows }) => {
  console.log(selection, selectedRows)
})

Checkbox columns are opt-in. Add one with selectColumn(); it renders a larger click target, supports selected-state sorting, and does not appear unless you add it to columns.

const columns = [selectColumn<Order>(), columnHelper.accessor('name', { header: 'Name' })]

Cell range selection can be disabled globally or for specific columns:

const table = useTable({ data, columns, enableCellSelection: false })

columnHelper.accessor('actions', {
  header: 'Actions',
  enableCellSelection: false,
})

Expanding Options

OptionTypeDefaultDescription
enableExpandingbooleantrueEnable row expanding
getSubRows(row, index) => TData[] | undefined--Return child rows for tree data
getRowCanExpand(row) => boolean--Custom expand-ability check
manualExpandingbooleanfalseDisable client-side expansion
paginateExpandedRowsboolean--Include expanded rows in pagination
renderDetailPanel(row) => unknown--Detail panel renderer
onExpandedChangeOnChangeFn<ExpandedState>--Expanded state change callback

Row Pinning Options

OptionTypeDefaultDescription
enableRowPinningboolean | (row) => booleanfalseEnable row pinning
keepPinnedRowsboolean--Keep pinned rows when filtering
onRowPinningChangeOnChangeFn<RowPinningState>--Row pinning change callback

Grouping Options

OptionTypeDefaultDescription
enableGroupingbooleanfalseEnable row grouping
manualGroupingbooleanfalseDisable client-side grouping
onGroupingChangeOnChangeFn<GroupingState>--Grouping change callback

Cell Editing Options

OptionTypeDefaultDescription
enableCellEditingboolean--Enable cell editing globally
onEditingChangeOnChangeFn<EditingState>--Editing state change callback
onEditCommit(changes: Record<string, Partial<TData>>) => void--Called when edits are committed

Event Handlers

OptionTypeDescription
onCellClick(event: CellClickEvent) => voidCell click handler
onCellDoubleClick(event: CellClickEvent) => voidCell double-click handler
onCellContextMenu(event: CellClickEvent) => voidCell right-click handler
onRowClick(event: RowClickEvent) => voidRow click handler
onRowDoubleClick(event: RowClickEvent) => voidRow double-click handler
onRowContextMenu(event: RowClickEvent) => voidRow right-click handler
onHeaderClick(event: HeaderClickEvent) => voidHeader click handler
onHeaderContextMenu(event: HeaderClickEvent) => voidHeader right-click handler

Export Options

OptionTypeDefaultDescription
enableExportboolean--Enable export functionality

Styling

OptionTypeDescription
rowClassNamestring | (row) => string | undefinedCSS class for rows
rowStyleCSSProperties | (row) => CSSPropertiesInline style for rows