Props and usage reference for the unified DataTable component
DataTable Reference
The single entry-point component: you pass config and actions as props; it composes the provider, UI, and table logic internally.
import { DataTable } from "@/components/ui/yayaw-table";For a minimal working setup you need tableType, getTableConfig, and getTableActions. See Provider & Setup for the full list and Next.js layout (NuqsAdapter, QueryClientProvider).
If no QueryClient is available from context (and no explicit queryClient prop is provided), DataTable now throws an explicit runtime error.
Props
List of available props for configuring DataTable.
tableType
The type of table configuration to use. Used to resolve config and actions (e.g. getTableConfig("products"), getTableActions("products")).
<DataTable tableType="products" />Required: true
tableId
Stable table instance id for URL state, cache keys, selection, pagination, and toolbar state. Defaults to tableType.
Use it when one table instance displays several business models but should still share one URL/cache/selection surface.
Type: string
formType
Default form configuration type for create/edit forms. Defaults to tableType. Table config can still override it with form.createFormType, form.editFormType, or form.resolveEditFormType(row).
Type: string
getTableConfig
Function that returns table and column configuration for the given tableType. Required for the table to know columns, sort, visibility, and options. See Configuration and Setup.
Type: (tableType: string) => Config | undefined
getTableActions
Function that returns actions (list, create, update, delete, bulk, etc.) for the given tableType. list is required for server-driven data. Can be Server Actions in Next.js. See Actions and Server-side & Server Actions.
Type: (tableType: string) => TableActions | undefined
getFormConfig
Function that returns form field definitions for create/edit and bulk edit dialogs. Optional but needed for forms.
Type: (formType: string, ctx?: FormConfigContext) => FormConfig | undefined
ctx includes { mode, tableId, tableType, formType, row, initialData, values }, so form fields can change for edit rows or for current create-form values.
queryClient
Optional explicit TanStack Query client instance. YaYaw Table no longer creates one internally. In most apps you should provide a shared app-level QueryClientProvider and omit this prop.
Type: QueryClient
className
Additional class names applied to the root wrapper.
Type: string | Default: undefined
loadingOverlay
Custom loading overlay to display while data is loading.
Type: React.ReactNode | Default: internal spinner overlay
<DataTable tableType="products" loadingOverlay={<MySpinner />} />onRowSelectionChange
Callback fired when selected rows change.
Type: (rows: Row<Record<string, unknown>>[]) => void | Default: undefined
onBulkEdit
Handle bulk edit of selected rows.
Type: (rows: Row<Record<string, unknown>>[]) => BulkActionResult | void | Promise<BulkActionResult | void> | Default: uses provider actions
onBulkDelete
Handle bulk deletion of selected rows.
Type: (rows: Row<Record<string, unknown>>[]) => BulkActionResult | BulkDeleteExecutionOutcome | void | Promise<...> | Default: uses provider bulkDelete / delete
onBulkCopy
Handle bulk duplication of selected rows.
Type: (rows: Row<Record<string, unknown>>[]) => BulkActionResult | void | Promise<BulkActionResult | void> | Default: internal clipboard copy
onExport
Override toolbar export behavior. Called with all rows matching current search/filters/sort state. If provided, default CSV download is skipped.
Type: (rows: Record<string, unknown>[]) => void \| Promise<void> | Default: internal CSV export
onBulkExport
Override bulk export behavior. Called with selected rows. If provided, default CSV download is skipped.
Type: (rows: Row<Record<string, unknown>>[]) => void \| Promise<void> | Default: internal CSV export
customBulkActions
Inject custom actions in the selected-row bulk actions menu. Supports a static array or a callback receiving live selected-row context.
Type: BulkAction<TData>[] | ((ctx: BulkActionContext<TData>) => BulkAction<TData>[]) | Default: undefined
Custom actions render after the built-in export action and before the built-in delete action. A custom action can be disabled from the current selection context, can ask for confirmation, and can return a BulkActionResult to control menu closing, selection clearing, and user feedback.
type BulkActionContext<TData> = {
selectedRows: Row<TData>[];
selectedOriginalRows: TData[];
selectedCount: number;
};
type BulkAction<TData> = {
id: string;
label: string;
icon: ComponentType<{ className?: string; size?: number }>;
onClick: (ctx: BulkActionContext<TData>) =>
| BulkActionResult
| void
| Promise<BulkActionResult | void>;
disabled?: boolean | ((ctx: BulkActionContext<TData>) => boolean);
variant?: "default" | "destructive";
confirm?: {
title?: string | ((ctx: BulkActionContext<TData>) => string);
description?: string | ((ctx: BulkActionContext<TData>) => string);
confirmLabel?: string | ((ctx: BulkActionContext<TData>) => string);
cancelLabel?: string | ((ctx: BulkActionContext<TData>) => string);
};
};toolbarActions
Inject custom actions in the main toolbar. Supports a static array or a callback receiving live toolbar context.
Type: ToolbarAction[] | ((ctx: ToolbarActionContext) => ToolbarAction[]) | Default: undefined
toolbarActionsPlacement
Control where custom toolbar actions are rendered relative to built-in actions.
Type: "before-create" | "between-create-export" | "after-export" | Default: "between-create-export"
ToolbarAction and ToolbarActionContext
type ToolbarAction = {
id: string;
label: string;
icon?: ReactNode;
onClick: (ctx: ToolbarActionContext) => void | Promise<void>;
disabled?: boolean | ((ctx: ToolbarActionContext) => boolean);
loading?: boolean;
variant?: "default" | "outline" | "secondary" | "ghost" | "destructive";
showInIconMode?: boolean; // default true
tooltip?: string;
};
type ToolbarActionContext = {
tableId: string;
actionsAsIcons: boolean;
isMobile: boolean;
isCreateEnabled: boolean;
isExportEnabled: boolean;
isExporting: boolean;
hasListAction: boolean;
selectedRows: Row<Record<string, unknown>>[];
selectedOriginalRows: Record<string, unknown>[];
selectedRowIds: string[];
selectedCount: number;
tableActions?: TableActions;
};Multi-Model Table
A single table can keep one tableId while resolving table config and form config separately:
<DataTable
tableId="cms-entries"
tableType="content-index"
formType="content-entry"
getTableConfig={(tableType) => ({
...configs[tableType],
form: {
createFormType: "content-entry",
resolveEditFormType: (row) => `${row.modelId}-entry`,
},
})}
getFormConfig={(formType, ctx) =>
buildEntryForm({
formType,
modelId: String(ctx?.values?.modelId ?? ctx?.row?.modelId ?? ""),
})
}
customBulkActions={(ctx) => [
{
id: "publish-selected",
label: "Publish",
icon: Send,
disabled: ctx.selectedCount === 0,
onClick: async () => publishEntries(ctx.selectedOriginalRows),
},
{
id: "archive-selected",
label: "Archive",
icon: Archive,
variant: "destructive",
disabled: ctx.selectedCount === 0,
confirm: {
title: "Archive selected entries?",
description: `Archive ${ctx.selectedCount} selected entries.`,
},
onClick: async () => archiveEntries(ctx.selectedOriginalRows),
},
]}
/>Here cms-entries owns URL/cache/selection, content-index owns the table columns and filters, and each row can open its own edit form type.
enableAdvancedFilters
Enable advanced filters UI when available in your configuration.
Type: boolean | Default: false
columnTypeMapping
Map dynamic backend types to internal column renderer types.
Type: Record<string, 'text' | 'number' | 'date' | 'option' | 'multiOption'> | Default: {}
Usage
<DataTable
tableType="products"
loadingOverlay={<MySpinner />}
onRowSelectionChange={(rows) => console.log(rows)}
onBulkDelete={(rows) => console.log("delete", rows.length)}
onExport={(rows) => console.log("export all", rows.length)}
onBulkExport={(rows) => console.log("export selected", rows.length)}
/>Custom action in text mode:
<DataTable
tableType="products"
toolbarActions={[
{
id: "recalculate-prices",
label: "Recalculate prices",
onClick: async () => {
await recalculatePrices();
},
variant: "secondary",
},
]}
/>Custom action in icon mode with tooltip and explicit placement:
<DataTable
tableType="products"
toolbarActions={(ctx) => [
{
id: "recalculate-prices",
label: "Recalculate prices",
tooltip: "Recalculate prices",
icon: <RefreshCw className="h-4 w-4" />,
disabled: () => !ctx.hasListAction || ctx.isExporting,
onClick: async () => {
await recalculatePrices();
},
},
]}
toolbarActionsPlacement="between-create-export"
/>Backward compatibility: if toolbarActions is omitted, toolbar behavior stays unchanged.
See also: