Components

Data Grid

A virtualized, editable spreadsheet-like data grid with sorting, filtering, grouping, cell selection, and keyboard navigation.

Client Only

Installation

pnpm dlx @docyrus/cli add @docyrus/ui-data-grid
UI Primitives(22 components)
npx shadcn@latest add action-bar avatar badge button calendar card checkbox command dialog direction dropdown-menu input kbd popover select separator skeleton sortable switch textarea toggle-group tooltip
Required Packages(5 packages)
pnpm add sonner @tanstack/react-table @radix-ui/react-direction @types/react @tanstack/react-virtual

Usage

import {
  DataGrid,
  DataGridFieldsMenu,
  DataGridFilterMenu,
  DataGridGroupMenu,
  DataGridKeyboardShortcuts,
  DataGridRowHeightMenu,
  DataGridSortMenu,
  DataGridViewMenu,
  getDataGridSelectColumn,
  useDataGrid
} from '@docyrus/ui/components/data-grid';
import type { ColumnDef, DataGridAction } from '@docyrus/ui/components/data-grid';

const columns: ColumnDef<Person>[] = [
  getDataGridSelectColumn<Person>(),
  {
    accessorKey: 'name',
    header: 'Name',
    size: 180,
    meta: { label: 'Name', cell: { variant: 'short-text' } }
  },
  {
    accessorKey: 'email',
    header: 'Email',
    size: 220,
    meta: { label: 'Email', cell: { variant: 'email' } }
  },
  {
    accessorKey: 'status',
    header: 'Status',
    size: 130,
    meta: {
      label: 'Status',
      cell: {
        variant: 'status',
        options: [
          { label: 'Active', value: 'active', color: '#22c55e' },
          { label: 'Inactive', value: 'inactive', color: '#ef4444' }
        ]
      }
    }
  }
];

function MyGrid() {
  const [data, setData] = useState(initialData);

  const { table, ...gridProps } = useDataGrid({
    data,
    columns,
    enableSearch: true,
    enableGrouping: true,
    onDataChange: setData,
    onRowAdd: () => {
      setData(prev => [...prev, emptyRow]);
      return null;
    },
    onRowsDelete: (rows, indices) => {
      setData(prev => prev.filter((_, i) => !indices.includes(i)));
    }
  });

  return (
    <div>
      <div className="mb-3 flex items-center gap-2">
        <DataGridFilterMenu table={table} />
        <DataGridSortMenu table={table} />
        <DataGridGroupMenu table={table} />
        <DataGridRowHeightMenu table={table} />
        <DataGridFieldsMenu table={table} />
        <DataGridViewMenu table={table} storageKey="my-grid" />
      </div>
      <DataGridKeyboardShortcuts enableSearch />
      <DataGrid table={table} {...gridProps} height={500} />
    </div>
  );
}

Toolbar Menus

The grid provides standalone toolbar menu components. Destructure table from useDataGrid and pass it to each menu:

ComponentDescription
DataGridFilterMenuColumn-based filter menu (integrates with DataTableFilter)
DataGridSortMenuMulti-column sort configuration
DataGridGroupMenuGroup rows by a single column
DataGridRowHeightMenuRow height selector (short, medium, tall, extra-tall)
DataGridFieldsMenuToggle column / card-body field visibility with searchable checklist + show-all / hide-all shortcuts
DataGridViewMenuColumn visibility, order, pinning, and saved views
DataGridAdvancedFilterDraft editor for an AND/OR filter group — OR, nesting and the full operator vocabulary, ANDed with the filter chips
DataGridKeyboardShortcutsKeyboard shortcut reference dialog (press / to open)

All menu components accept table: Table<TData> and an optional disabled?: boolean prop.

Action Column

Use getDataGridActionsColumn to create a per-row action column. It sets sensible defaults (header: () => null, non-hideable, non-resizable, non-sortable) and auto-calculates column width from the number of action buttons.

import { getDataGridActionsColumn } from '@docyrus/ui/components/data-grid';

const actionColumn = getDataGridActionsColumn<Person>({
  cell: ({ row }) => (
    <div className="flex items-center gap-0.5">
      <Button variant="ghost" size="icon" className="size-7" onClick={() => onExpand(row.original)}>
        <Expand className="size-4" />
      </Button>
      <DropdownMenu>
        <DropdownMenuTrigger asChild>
          <Button variant="ghost" size="icon" className="size-7">
            <MoreHorizontal className="size-4" />
          </Button>
        </DropdownMenuTrigger>
        <DropdownMenuContent align="end">
          <DropdownMenuItem onClick={() => onEdit(row.original)}>
            <Pencil className="size-4" /> Edit
          </DropdownMenuItem>
          <DropdownMenuSeparator />
          <DropdownMenuItem variant="destructive" onClick={() => onDelete(row.original)}>
            <Trash2 className="size-4" /> Delete
          </DropdownMenuItem>
        </DropdownMenuContent>
      </DropdownMenu>
    </div>
  )
});

const columns = [
  getDataGridSelectColumn<Person>(),
  actionColumn,
  ...dataColumns
];

By default, visibleOnHover is enabled — action buttons are hidden and fade in on row hover using CSS @media (hover: hover). On touch screens the buttons are always visible. To keep buttons always visible on all devices, set visibleOnHover: false.

const actionColumn = getDataGridActionsColumn<Person>({
  visibleOnHover: false,
  actionCount: 1,
  cell: ({ row }) => (
    <Button variant="ghost" size="icon" className="size-7">
      <MoreHorizontal className="size-4" />
    </Button>
  )
});

Bulk Actions

Show action buttons in a floating bar when rows are selected. The bar appears at the bottom of the grid with a count of selected rows and a dismiss button that clears the selection.

const actions: DataGridAction<Person>[] = [
  {
    label: 'Export',
    icon: <Download className="size-3.5" />,
    onAction: (rows) => exportToCsv(rows)
  },
  {
    label: 'Delete',
    icon: <Trash2 className="size-3.5" />,
    variant: 'destructive',
    onAction: (rows) => deleteRows(rows)
  }
];

<DataGrid table={table} {...gridProps} actions={actions} />

Change Tracking

Enable batch editing with enableChangeTracking. Edits are tracked in-memory and displayed with amber highlights. A floating action bar shows pending changes with Cancel/Save buttons.

import type { RowChange } from '@docyrus/ui/components/data-grid';

const { table, ...gridProps } = useDataGrid({
  data,
  columns,
  enableChangeTracking: true,
  onDataChange: setData,
  onChangesSave: async (changes: RowChange[], data) => {
    await api.batchUpdate(changes);
  },
  onChangesDiscard: () => {
    // Optional: called when user clicks Cancel
  },
  getRowLabel: (row) => row.name
});

Changed cells are highlighted with an amber background and left border. The floating action bar shows the count of modified rows and a popover with field-level change details (old value → new value). Editing a cell back to its original value automatically removes the highlight.

Skeleton

Use the skeleton components to show a loading placeholder while data is fetching.

import {
  DataGridSkeleton,
  DataGridSkeletonToolbar,
  DataGridSkeletonGrid
} from '@docyrus/ui/components/data-grid';

<DataGridSkeleton>
  <DataGridSkeletonToolbar actionCount={4} align="end" />
  <DataGridSkeletonGrid />
</DataGridSkeleton>

Views

Use DataGridViewSelect and DataGridViewEditor to let users switch between saved views and create or edit custom ones. Views control column visibility, order, pinning, and sorting.

import { applyViewToTable, type SavedDataGridView } from '@docyrus/ui/components/data-grid';
import { DataGridViewSelect } from '@docyrus/ui/components/data-grid-view-select';
import { DataGridViewEditor } from '@docyrus/ui/components/data-grid-view-select';

const [views, setViews] = useState<SavedDataGridView[]>(initialViews);
const [activeViewId, setActiveViewId] = useState('view-all');
const [editorOpen, setEditorOpen] = useState(false);
const [editingView, setEditingView] = useState<SavedDataGridView | undefined>();

<DataGridViewSelect
  table={table}
  variant="horizontal-tabs"
  views={views}
  activeViewId={activeViewId}
  onViewChange={(view) => setActiveViewId(view.id)} />

<DataGridViewEditor
  table={table}
  open={editorOpen}
  onOpenChange={setEditorOpen}
  value={editingView}
  onSave={(view) => {
    setViews(prev => {
      const idx = prev.findIndex(v => v.id === view.id);
      return idx >= 0
        ? prev.map(v => v.id === view.id ? view : v)
        : [...prev, view];
    });
    setActiveViewId(view.id);
    applyViewToTable(table, view);
  }}
  onDelete={(viewId) => setViews(prev => prev.filter(v => v.id !== viewId))}
  showDelete={editingView !== undefined && views.length > 1} />

DataGridViewSelect

PropTypeDefaultDescription
tableTable<TData>—TanStack table instance
variant'dropdown' | 'horizontal-tabs' | 'vertical-tabs''dropdown'Display variant
viewsSavedDataGridView[]—Available views
activeViewIdstring—Currently active view ID
onViewChange(view: SavedDataGridView) => void—Called when user selects a view

DataGridViewEditor

PropTypeDefaultDescription
tableTable<TData>—TanStack table instance
openboolean—Whether the editor is open
onOpenChange(open: boolean) => void—Called when open state changes
valueSavedDataGridView | undefined—View to edit (undefined for new)
onSave(view: SavedDataGridView) => void—Called when view is saved
onDelete(viewId: string) => void—Called when view is deleted
showDeletebooleanfalseShow delete button

SavedDataGridView

FieldTypeDescription
idstringUnique view identifier
namestringDisplay name
descriptionstringOptional description
columnVisibilityRecord<string, boolean>Column visibility map
columnOrderstring[]Column order array
columnPinning{ left: string[], right: string[] }Pinned columns
sortingSortingStateOptional sorting configuration

Color Rules

Conditionally highlight rows or individual cells based on data values using JSONata expressions. Row rules apply a background color to the entire row; cell rules target a specific column. Rules are evaluated in order — the first matching rule wins.

import type {
  DataGridRowColorRule,
  DataGridCellColorRule
} from '@docyrus/ui/components/data-grid';

const rowColorRules: DataGridRowColorRule[] = [
  { formula: 'status = "Cancelled"', color: 'red-50' },
  { formula: 'total > 10000', color: 'green-50' }
];

const cellColorRules: DataGridCellColorRule[] = [
  { column: 'priority', formula: 'priority = "Urgent"', color: 'red-100' },
  { column: 'total', formula: 'total > 5000', color: 'emerald-100' }
];

const { table, ...gridProps } = useDataGrid({
  data,
  columns,
  rowColorRules,
  cellColorRules
});

The color field accepts Tailwind color names (e.g. red-50, emerald-100) or raw hex values (e.g. #fef2f2). Formulas are standard JSONata expressions evaluated against each row's data object.

Color rules have lower visual priority than interactive states — selected cells, search matches, change-tracked cells, and cut cells will override color rule backgrounds.

Chart Cells

Render mini sparklines or bar charts inside cells with an optional expand popover for detailed visualizations. The cell value should be an array of numbers or data point objects.

const columns: ColumnDef<Product>[] = [
  {
    accessorKey: 'trend',
    header: 'Revenue Trend',
    size: 160,
    meta: {
      cell: {
        variant: 'chart',
        chartType: 'sparkline',
        color: '#10b981',
        expandedCellContent: (rowData) => {
          const row = rowData as Product;
          return (
            <div className="space-y-2">
              <h4 className="font-medium">{row.name} — Detailed Trend</h4>
              {/* Full chart, stats, grid, etc. */}
            </div>
          );
        }
      }
    }
  },
  {
    accessorKey: 'weeklyUnits',
    header: 'Weekly Units',
    size: 140,
    meta: {
      cell: {
        variant: 'chart',
        chartType: 'bar',
        dataKey: 'units',
        color: '#8b5cf6'
      }
    }
  }
];

The expand icon appears on hover when expandedCellContent is provided, opening a popover with user-defined content. The expandedCellContent function receives the full row data object (row.original), allowing dynamic rendering based on any field.

OptionTypeDefaultDescription
chartType'sparkline' | 'bar''sparkline'Line chart or mini bar chart
dataKeystring'value'Key to read from each data point object
colorstringTheme primaryStroke (sparkline) or fill (bar) color
expandedCellContent(rowData: unknown) => ReactNode—Render function for the expanded popover content

DataGridRowColorRule

FieldTypeDescription
formulastringJSONata expression evaluated against row data. Row is highlighted when the expression returns a truthy value.
colorstringTailwind color name (e.g. red-50) or hex value (e.g. #fef2f2)

DataGridCellColorRule

FieldTypeDescription
columnstringColumn ID (accessorKey) to apply the color to
formulastringJSONata expression evaluated against row data. Cell is highlighted when the expression returns a truthy value.
colorstringTailwind color name (e.g. amber-100) or hex value (e.g. #fef3c7)

Features

  • Virtualized rendering — Only visible rows are rendered for optimal performance
  • Cell editing — Click to select, double-click or type to edit
  • Keyboard navigation — Arrow keys, Tab, Enter, Escape, Home, End, Page Up/Down
  • Cell selection — Click + Shift/Ctrl for multi-cell range selection
  • Copy / Cut / Paste — Ctrl+C, Ctrl+X, Ctrl+V with clipboard support
  • Search — Ctrl+F to open in-grid search bar
  • Context menu — Right-click for cell actions
  • Row selection — Select column with checkboxes for bulk operations
  • Row height — Built-in row height menu (short, medium, tall, extra-tall)
  • Sorting — Column header sort menu
  • Filtering — Column header filter menu
  • Grouping — Group rows by column values
  • Paging — Optional standard paging footer with page-size selector
  • RTL support — Full right-to-left layout
  • Add / Delete rows — Footer add row button, bulk delete via action bar
  • Change tracking — Batch edit workflow with amber highlights, cancel/save action bar
  • 30 cell variants — Comprehensive cell types for any data

Paging

The grid supports two row layouts, controlled by the pagingMode option on useDataGrid (and forwarded through gridProps):

  • virtual-scroll (default) — every loaded row is rendered in a single virtualized viewport. No footer. Best for grids that load all rows at once or lazily via infinite scroll.
  • standard — rows are paginated client-side and a paging footer (<DataGridPaginationFooter>) is shown beneath the grid with first/prev/next/last buttons, the current page / total indicator, and a page-size selector.

Page-size choices come from DATA_GRID_PAGE_SIZE_OPTIONS ([25, 50, 100, 200, 250, 500]); the default is DATA_GRID_DEFAULT_PAGE_SIZE (50).

import {
  DataGrid,
  useDataGrid
} from '@docyrus/ui/components/data-grid';

const { table, ...gridProps } = useDataGrid<Task>({
  data,
  columns,
  pagingMode: 'standard',
  pageSize: 50
});

// Spread `gridProps` — `pagingMode` flows through automatically.
return <DataGrid table={table} {...gridProps} height="auto" />;

When paired with DataGridViewSelect, saved views own the paging configuration via their Paging section (toggle the footer, pick the mode, choose the page size). The Docyrus-aware useDocyrusDataGrid hook reads those view settings and forwards them to useDataGrid so the footer follows the active view automatically.


API Reference

useDataGrid

The main hook that manages all grid state. Returns an object to spread onto <DataGrid>.

PropTypeDefaultDescription
dataArray<TData>—Row data array
columnsArray<ColumnDef<TData>>—Column definitions (TanStack Table)
onDataChange(data: Array<TData>) => void—Called when cell values change
onRowAdd(event?) => Partial<CellPosition> | Promise<...> | null—Called when "Add row" is clicked. Returning null appends at end.
onRowsAdd(count: number) => void | Promise<void>—Called when pasting requires new rows
onRowsDelete(rows: Array<TData>, indices: Array<number>) => void | Promise<void>—Called on row deletion (bulk or single)
onPaste(updates: Array<CellUpdate>) => void | Promise<void>—Custom paste handler
onFilesUpload(params) => Promise<Array<FileCellData>>—File upload handler for file/image cells
onFilesDelete(params) => void | Promise<void>—File deletion handler
rowHeightRowHeightValue'short'Initial row height (read once at mount)
onRowHeightChange(height: RowHeightValue) => void—Row height change callback
overscannumber4Virtual scroll overscan rows
measureRowsbooleanfalseMeasure variable row heights; keep off for uniform rows to avoid layout thrash
dir'ltr' | 'rtl'—Text direction
autoFocusboolean | Partial<CellPosition>—Auto-focus grid or specific cell on mount
enableSingleCellSelectionbooleanfalseAllow single cell click selection
enableColumnSelectionbooleanfalseAllow full column selection via header
enableSearchbooleanfalseEnable Ctrl+F search bar
enablePastebooleanfalseEnable clipboard paste
enableGroupingbooleantrueEnable column grouping
readOnlyboolean—Disable all editing
enableChangeTrackingbooleanfalseTrack cell edits and show amber highlights with a save/cancel action bar
onChangesSave(changes: Array<RowChange>, data: Array<TData>) => void | Promise<void>—Called when user clicks Save with all pending changes and current data
onChangesDiscard() => void—Called when user clicks Cancel (data is automatically reverted)
getRowLabel(row: TData, rowIndex: number) => string—Custom row label for the changes popover (defaults to Row {index + 1})
rowColorRulesArray<DataGridRowColorRule>—Conditional row background color rules using JSONata formulas
cellColorRulesArray<DataGridCellColorRule>—Conditional cell background color rules using JSONata formulas
initialStateTableState (TanStack)—Pass-through initial state (sorting, columnVisibility, pinning, etc.)
formatDate(value: unknown) => string—Custom date formatter for date cells. Without a formatter, raw value is displayed.
formatDateTime(value: unknown) => string—Custom datetime formatter for datetime cells. Without a formatter, raw value is displayed.
formatNumber(value: unknown, opts?: { variant?: 'number' | 'currency' | 'percent'; currency?: string; decimalPrecision?: number; thousandSeparator?: string }) => string—Tenant-aware numeric formatter for number / currency / percent cells (and their gallery card rendering). Adapters should forward decimalPrecision / thousandSeparator so per-column overrides (e.g. field-autonumber) take effect; without a formatter, the built-in fallback honors the same opts.
pagingMode'standard' | 'virtual-scroll'—When 'standard', the returned gridProps.pagingMode makes <DataGrid> render the paging footer. When unset or 'virtual-scroll', all rows render in a single virtualized viewport.
pageSizenumber50Initial page size used by TanStack pagination when pagingMode === 'standard'.

DataGrid

The rendered grid component. Accepts the return value of useDataGrid plus visual props.

PropTypeDefaultDescription
...useDataGrid()ReturnType<typeof useDataGrid>—Spread the hook's return value
dir'ltr' | 'rtl''ltr'Layout direction
heightnumber600Grid height in pixels
stretchColumnsbooleanfalseStretch columns to fill available width
addRowLabelstring'Add row'Label for the add row button
actionsArray<DataGridAction<TData>>—Bulk action buttons for selected rows
pagingMode'standard' | 'virtual-scroll'—Renders the paging footer when 'standard'. Inherited from gridProps; pass explicitly to override.

DataGridAdvancedFilter

A popover-hosted QueryBuilderDocyrus for the one query the chip bar cannot express: status = Active OR owner = me. The chip bar holds exactly one rule per column, all ANDed, with no combinator control — this is the surface for OR, nesting and the full operator vocabulary, without having to save a view.

It is a draft editor: nothing is emitted until Apply, and Apply prunes the group first (a rule with no field yet, or a between holding an empty string, is a hard error on the items endpoint; a freshly added empty group silently returns zero rows). Limits are 10 rules and 2 levels of nesting.

PropTypeDefaultDescription
tableTable<TData>—The TanStack table instance. Columns are read from it to build the field list.
groupRuleGroupType | undefined—The group currently applied, or undefined when none is.
onChange(group: RuleGroupType | undefined) => void—Called on Apply with the pruned group, or undefined when the group is cleared.
disabledbooleanfalseDisable the trigger.
classNamestring—Extra className for the trigger.

useDocyrusDataGrid mounts this automatically as part of enableFilterMenu and stores the group under a reserved columnFilters entry — see Advanced AND/OR filtering.

DataGridPaginationFooter

The standalone paging footer rendered at the bottom of <DataGrid> when pagingMode === 'standard'. Exposed as a re-export so consumers building bespoke grid wrappers can position it themselves.

PropTypeDefaultDescription
tableTable<TData>—TanStack Table instance from useDataGrid
pageSizeOptionsReadonlyArray<number>DATA_GRID_PAGE_SIZE_OPTIONS ([25, 50, 100, 200, 250, 500])Page-size choices in the footer's selector

DataGridSkeleton

Container for the loading skeleton.

PropTypeDefaultDescription
classNamestring—Additional CSS classes

DataGridSkeletonToolbar

Toolbar skeleton with placeholder action buttons.

PropTypeDefaultDescription
align'start' | 'center' | 'end''end'Toolbar alignment
actionCountnumber4Number of placeholder action buttons

DataGridSkeletonGrid

Grid body skeleton placeholder.

PropTypeDefaultDescription
classNamestring—Additional CSS classes

getDataGridSelectColumn

Returns a column definition (id: 'select') that renders a row selection checkbox column. The header shows a "select all" checkbox with indeterminate state. Each cell shows a checkbox that supports Shift+Click for range selection via tableMeta.onRowSelect.

const selectColumn = getDataGridSelectColumn<Person>({
  size: 44,
  enableRowMarkers: true
});
const columns = [selectColumn, ...yourColumns];
OptionTypeDefaultDescription
sizenumber40Column width in pixels
enableRowMarkersbooleanfalseShow row numbers when checkbox is unchecked. Numbers appear on hover and disappear when the row is checked.
readOnlybooleanfalseRender as read-only row numbers without checkboxes
hitboxSize'default' | 'sm' | 'lg''default'Clickable area padding around the checkbox
debugbooleanfalseShow a red dashed border around the clickable hitbox area (development only)
enableHidingbooleanfalseWhether the column can be hidden via view menu
enableResizingbooleanfalseWhether the column width can be resized
enableSortingbooleanfalseWhether the column is sortable

Any additional ColumnDef props (except id, header, cell) are passed through to the returned column definition.

getDataGridActionsColumn

Returns a column definition (id: 'actions') for per-row action buttons. Sets header: () => null so the cell content renders directly without the standard cell wrapper. Column width is auto-calculated from actionCount when size is not provided.

const actionColumn = getDataGridActionsColumn<Person>({
  cell: ({ row }) => (
    <Button variant="ghost" size="icon" className="size-7">
      <MoreHorizontal className="size-4" />
    </Button>
  )
});
const columns = [getDataGridSelectColumn<Person>(), actionColumn, ...yourColumns];
OptionTypeDefaultDescription
actionCountnumber2Number of inline action buttons. Used to auto-calculate column width when size is not provided.
visibleOnHoverbooleantrueHide cell content until row hover on non-touch screens. Uses CSS @media (hover: hover) with transition-opacity.
sizenumberautoColumn width in pixels. If omitted, calculated as actionCount × 28 + (actionCount − 1) × 2 + 12.
enableHidingbooleanfalseWhether the column can be hidden via view menu
enableResizingbooleanfalseWhether the column width can be resized
enableSortingbooleanfalseWhether the column is sortable

The cell prop must be provided by the user. Any additional ColumnDef props (except id, header, meta) are passed through.


Type Reference

ColumnDef

Re-exported from @tanstack/react-table. Extended with meta fields for cell variant configuration and display behavior.

{
  accessorKey: string;
  header: string | (() => ReactNode);
  size?: number;
  meta?: {
    label?: string;
    group?: string;
    cell?: CellOpts;
    visibleOnHover?: boolean;
    format?: (value: TValue, row: TData) => string;
  };
}
Meta FieldTypeDescription
labelstringDisplay name used in menus, change tracking popover, and filter/sort/group UIs
groupstringColumn grouping category
cellCellOptsCell variant and its configuration
visibleOnHoverbooleanHide cell content until row hover on non-touch screens
format(value: TValue, row: TData) => stringCustom formatter for cell display and export

CellOpts

A discriminated union defining the cell variant and its configuration. Set via meta.cell on column definitions.

VariantAdditional PropsData TypeDescription
short-text—stringSingle-line text input
long-text—stringMulti-line text with expand
email—stringEmail with mailto link
phone—stringPhone number with tel link
numbermin?, max?, step?, decimalPrecision?, thousandSeparator?numberNumeric input with constraints. Pass decimalPrecision: 0 + thousandSeparator: '' to render identifier-like values (e.g. autonumber: 394 instead of 394.00). useDocyrusFieldComponent applies these defaults for field-autonumber automatically.
currencycurrency?, min?, max?, step?, decimalPrecision?, thousandSeparator?numberFormatted currency value. Precision/grouping overrides override the locale defaults.
percentmin?, max?, step?, decimalPrecision?, thousandSeparator?numberPercentage display (0-1 range).
url—stringClickable URL link
checkbox—booleanBoolean checkbox
switch—booleanBoolean toggle switch
selectoptions: CellSelectOption[], display?stringSingle-select dropdown. display: 'text' renders as plain text instead of badge
statusoptions: CellSelectOption[], display?stringColor-coded status. display: 'text' renders as plain text instead of badge
enumappSlug, dataSourceSlug, fieldSlug, options?, display?stringBackend-driven enum. display: 'text' renders as plain text instead of badge
useroptions: CellUserOption[]stringUser avatar + name select
multi-selectoptions: CellSelectOption[]stringMulti-value select with badges
tag-selectoptions: CellSelectOption[]stringColored tag chips
date—stringDate picker (YYYY-MM-DD)
datetime—stringDate + time picker (ISO 8601)
time—stringTime-only picker (HH:mm)
duration—stringDuration display (HH:mm:ss)
date-range—stringDate range (start,end)
color—stringColor swatch + hex picker
icon—stringIcon name selector
currency-code—stringISO currency code (USD, EUR, etc.)
filemaxFileSize?, maxFiles?, accept?, multiple?FileCellData[]File upload cell
imagemaxFileSize?, accept?stringImage preview + upload
relationdataSourceId, displayField?stringRelated record lookup (requires Docyrus)
ratingmax?numberStar rating (default max: 5)
user-multi-selectoptions: CellUserOption[]stringMulti-user select with avatars
chartchartType?, dataKey?, color?, expandedCellContent?number[] or object[]Mini sparkline or bar chart (read-only)

CellSelectOption

Option definition for select, status, multi-select, and tag-select variants.

FieldTypeRequiredDescription
labelstringYesDisplay label
valuestringYesInternal value
iconFC<SVGProps>NoCustom icon component
iconStrstringNoIcon name string
colorstringNoBadge/tag color (hex)
countnumberNoFaceted count

CellUserOption

Extends CellSelectOption with user-specific fields.

FieldTypeRequiredDescription
...CellSelectOption——All select option fields
avatarUrlstringNoUser avatar image URL
initialsstringNoFallback initials (e.g. "AJ")

DataGridAction

Action button definition for the bulk action bar (shown when rows are selected).

FieldTypeRequiredDescription
labelstringYesAction button label
iconReactNodeNoAction icon
variant'default' | 'destructive'NoButton variant
onAction(selectedRows: Array<TData>) => voidYesAction callback with selected rows

CellChange

Represents a single cell's change within a row.

FieldTypeDescription
columnIdstringColumn ID of the changed cell
originalValueunknownValue before editing
newValueunknownCurrent edited value

RowChange

Represents all changes in a single row. Passed to onChangesSave as an array.

FieldTypeDescription
rowIdstringRow identifier
rowIndexnumberRow index in the data array
changesMap<string, CellChange>Map of column ID → cell change

RowHeightValue

type RowHeightValue = 'short' | 'medium' | 'tall' | 'extra-tall';

CellUpdate

Used in paste and data update operations.

FieldTypeDescription
rowIndexnumberTarget row index
columnIdstringTarget column ID
valueunknownNew cell value

CellPosition

FieldTypeDescription
rowIndexnumberRow index
columnIdstringColumn ID

FileCellData

Data shape for files in file and image cell variants.

FieldTypeDescription
idstringUnique file ID
namestringFile name
sizenumberFile size in bytes
typestringMIME type
urlstring?Download/preview URL

Direction

type Direction = 'ltr' | 'rtl';

Keyboard Shortcuts

ShortcutAction
Arrow KeysNavigate between cells
Tab / Shift+TabMove to next/previous cell
EnterStart editing / Confirm edit
EscapeCancel edit / Clear selection
Ctrl+FOpen search
Ctrl+CCopy selected cells
Ctrl+XCut selected cells
Ctrl+VPaste from clipboard
Ctrl+ASelect all cells
Delete / BackspaceClear selected cells
Home / EndJump to first/last cell in row
Ctrl+Home / Ctrl+EndJump to first/last cell in grid
Page Up / Page DownScroll up/down by page
Shift+ClickRange selection
Ctrl+ClickToggle cell in selection

On this page