react-data-grid
Version:
Feature-rich and customizable data grid React component
1,789 lines (1,252 loc) • 56.8 kB
Markdown
# react-data-grid
[![npm-badge]][npm-url]
[![type-badge]][npm-url]
[![size-badge]][size-url]
[![codecov-badge]][codecov-url]
[![ci-badge]][ci-url]
The DataGrid component is designed to handle large datasets efficiently while offering a rich set of features for customization and interactivity.
## Table of contents
- [Features](#features)
- [Links](#links)
- [Installation](#installation)
- [Getting started](#getting-started)
- [Styling and Customization](#styling-and-customization)
- [API Reference](#api-reference)
## Features
- [React 19.2+](package.json) support
- Evergreen browsers and server-side rendering support
- Tree-shaking support with no external dependencies to keep your bundles slim
- Great performance thanks to virtualization: columns and rows outside the viewport are not rendered
- Strictly typed with TypeScript
- [Keyboard accessibility](https://comcast.github.io/react-data-grid/#/CommonFeatures)
- Light and dark mode support out of the box via `color-scheme`.
- [Frozen columns](https://comcast.github.io/react-data-grid/#/CommonFeatures): Freeze columns to keep them visible during horizontal scrolling.
- [Column resizing](https://comcast.github.io/react-data-grid/#/CommonFeatures)
- [Multi-column sorting](https://comcast.github.io/react-data-grid/#/CommonFeatures)
- Click on a sortable column header to toggle between its ascending/descending sort order
- Ctrl+Click / Meta+Click to sort an additional column
- [Column spanning](https://comcast.github.io/react-data-grid/#/ColumnSpanning)
- [Column grouping](https://comcast.github.io/react-data-grid/#/ColumnGrouping)
- [Row selection](https://comcast.github.io/react-data-grid/#/CommonFeatures)
- [Row grouping](https://comcast.github.io/react-data-grid/#/RowGrouping)
- [Summary rows](https://comcast.github.io/react-data-grid/#/CommonFeatures)
- [Dynamic row heights](https://comcast.github.io/react-data-grid/#/VariableRowHeight)
- [No rows fallback](https://comcast.github.io/react-data-grid/#/NoRows)
- [Cell formatting](https://comcast.github.io/react-data-grid/#/CommonFeatures)
- [Cell editing](https://comcast.github.io/react-data-grid/#/CommonFeatures)
- [Cell copy / pasting](https://comcast.github.io/react-data-grid/#/AllFeatures)
- [Cell value dragging / filling](https://comcast.github.io/react-data-grid/#/AllFeatures)
- [Customizable Renderers](https://comcast.github.io/react-data-grid/#/CustomizableRenderers)
- Right-to-left (RTL) support.
## Links
- [Examples website](https://comcast.github.io/react-data-grid/)
- [Source code](website)
- [Changelog](CHANGELOG.md)
## Installation
Install `react-data-grid` using your favorite package manager:
```sh
npm i react-data-grid
```
```sh
pnpm add react-data-grid
```
```sh
yarn add react-data-grid
```
```sh
bun add react-data-grid
```
Additionally, import the default styles in your application:
```tsx
import 'react-data-grid/lib/styles.css';
```
`react-data-grid` is published as ECMAScript modules for evergreen browsers, bundlers, and server-side rendering.
> **Important** <br />
> Vite 8+ by default uses `lightningcss` to minify css which has a [bug minifying light-dark syntax](https://github.com/parcel-bundler/lightningcss/issues/873). You can tweak the `cssMinify` or `cssTarget` [settings](https://main.vite.dev/config/build-options) as a workaround.
```ts
build: {
cssMinify: 'esbuild',
// or
cssTarget: 'esnext'
}
```
## Getting started
Here is a basic example of how to use `react-data-grid` in your React application:
```tsx
import 'react-data-grid/lib/styles.css';
import { DataGrid, type Column } from 'react-data-grid';
interface Row {
id: number;
title: string;
}
const columns: readonly Column<Row>[] = [
{ key: 'id', name: 'ID' },
{ key: 'title', name: 'Title' }
];
const rows: readonly Row[] = [
{ id: 0, title: 'Example' },
{ id: 1, title: 'Demo' }
];
function App() {
return <DataGrid columns={columns} rows={rows} />;
}
```
## Styling and Customization
The DataGrid provides multiple ways to customize its appearance and behavior.
### Light/Dark Themes
The DataGrid supports both light and dark color schemes out of the box using the `light-dark()` CSS function. The theme automatically adapts based on the user's system preference when `color-scheme: light dark;` is set.
To enforce a specific theme, we recommend setting the standard `color-scheme` CSS property on the `:root`:
```css
:root {
color-scheme: light; /* or 'dark', or 'light dark' for auto */
}
```
Alternatively, you can add the `rdg-light` or `rdg-dark` class to individual grids:
```tsx
// Force light theme
<DataGrid className="rdg-light" columns={columns} rows={rows} />
// Force dark theme
<DataGrid className="rdg-dark" columns={columns} rows={rows} />
```
### CSS Variables
The DataGrid supports the following CSS variables for customization:
```css
.rdg {
/* Selection */
--rdg-selection-width: 2px;
--rdg-selection-color: hsl(207, 75%, 66%);
/* Typography */
--rdg-font-size: 14px;
/* Colors (using light-dark() for automatic theme switching) */
--rdg-color: light-dark(#000, #ddd);
--rdg-background-color: light-dark(hsl(0deg 0% 100%), hsl(0deg 0% 13%));
/* Header */
--rdg-header-background-color: light-dark(hsl(0deg 0% 97.5%), hsl(0deg 0% 10.5%));
--rdg-header-draggable-background-color: light-dark(hsl(0deg 0% 90.5%), hsl(0deg 0% 17.5%));
/* Rows */
--rdg-row-hover-background-color: light-dark(hsl(0deg 0% 96%), hsl(0deg 0% 9%));
--rdg-row-selected-background-color: light-dark(hsl(207deg 76% 92%), hsl(207deg 76% 42%));
--rdg-row-selected-hover-background-color: light-dark(hsl(207deg 76% 88%), hsl(207deg 76% 38%));
/* Borders */
--rdg-border-width: 1px;
--rdg-border-color: light-dark(#ddd, #444);
--rdg-summary-border-width: calc(var(--rdg-border-width) * 2);
--rdg-summary-border-color: light-dark(#aaa, #555);
/* Checkboxes */
--rdg-checkbox-focus-color: hsl(207deg 100% 69%);
}
```
Example of customizing colors:
```css
.my-custom-grid {
--rdg-background-color: #f0f0f0;
--rdg-selection-color: #ff6b6b;
--rdg-font-size: 16px;
}
```
```tsx
<DataGrid className="my-custom-grid" columns={columns} rows={rows} />
```
### Standard Props
The DataGrid accepts standard [`className`](#classname-string--undefined) and [`style`](#style-cssproperties--undefined) props:
```tsx
<DataGrid
columns={columns}
rows={rows}
className="my-grid custom-theme"
style={{ width: 800, height: 600 }}
/>
```
### Row and Cell Styling
#### Row Heights
Control row heights using the [`rowHeight`](#rowheight-maybenumber--row-r--number), [`headerRowHeight`](#headerrowheight-maybenumber), and [`summaryRowHeight`](#summaryrowheight-maybenumber) props. The `rowHeight` prop supports both fixed heights and dynamic heights per row.
#### Row Classes
Apply custom CSS classes to rows using the [`rowClass`](#rowclass-mayberow-r-rowidx-number--maybestring) prop, and to header rows using the [`headerRowClass`](#headerrowclass-maybestring) prop.
#### Cell Classes
Apply custom CSS classes to cells using the [`cellClass`](#cellclass-maybestring--row-trow--maybestring) property in column definitions. You can also use [`headerCellClass`](#headercellclass-maybestring) and [`summaryCellClass`](#summarycellclass-maybestring--row-tsummaryrow--maybestring) for header and summary cells respectively.
#### Column Widths
Control column widths using the [`width`](#width-maybenumber--string), [`minWidth`](#minwidth-maybenumber), and [`maxWidth`](#maxwidth-maybenumber) properties in column definitions. Enable column resizing using the [`resizable`](#resizable-maybeboolean) property, or use [`defaultColumnOptions`](#defaultcolumnoptions-maybedefaultcolumnoptionsr-sr) to apply it to all columns.
### Custom Renderers
Replace default components with custom implementations using the [`renderers`](#renderers-mayberenderersr-sr) prop. Columns can also have custom renderers using the [`renderCell`](#rendercell-maybeprops-rendercellpropstrow-tsummaryrow--reactnode), [`renderHeaderCell`](#renderheadercell-maybeprops-renderheadercellpropstrow-tsummaryrow--reactnode), [`renderSummaryCell`](#rendersummarycell-maybeprops-rendersummarycellpropstsummaryrow-trow--reactnode), [`renderGroupCell`](#rendergroupcell-maybeprops-rendergroupcellpropstrow-tsummaryrow--reactnode), and [`renderEditCell`](#rendereditcell-maybeprops-rendereditcellpropstrow-tsummaryrow--reactnode) properties.
## API Reference
### Components
#### `<DataGrid />`
##### DataGridProps
###### `columns: readonly ColumnOrColumnGroup<R, SR>[]`
An array of column definitions and/or column groups. See the [`ColumnOrColumnGroup`](#columnorcolumngrouptrow-tsummaryrow) type for all available options.
:warning: **Performance:** Passing a new `columns` array will trigger a re-render and recalculation for the entire grid. Always memoize this prop using `useMemo` or define it outside the component to avoid unnecessary re-renders.
###### `rows: readonly R[]`
An array of rows, the rows data can be of any type.
:bulb: **Performance:** The grid is optimized for efficient rendering:
- **Virtualization**: Only visible rows are rendered in the DOM
- **Individual row updates**: Row components are memoized, so updating a single row object will only re-render that specific row, not all rows
- **Array reference matters**: Changing the array reference itself (e.g., `setRows([...rows])`) triggers viewport and layout recalculations, even if the row objects are unchanged
- **Best practice**: When updating rows, create a new array but reuse unchanged row objects. For example:
```tsx
// ✅ Good: Only changed row is re-rendered
setRows(rows.map((row, idx) => (idx === targetIdx ? { ...row, updated: true } : row)));
// ❌ Avoid: Creates new references for all rows, causing all visible rows to re-render
setRows(rows.map((row) => ({ ...row })));
```
###### `ref?: Maybe<React.Ref<DataGridHandle>>`
Optional ref for imperative APIs like scrolling to or focusing a cell. See [`DataGridHandle`](#datagridhandle).
###### `topSummaryRows?: Maybe<readonly SR[]>`
Rows pinned at the top of the grid for summary purposes.
###### `bottomSummaryRows?: Maybe<readonly SR[]>`
Rows pinned at the bottom of the grid for summary purposes.
###### `rowKeyGetter?: Maybe<(row: R) => K>`
Function to return a unique key/identifier for each row. `rowKeyGetter` is required for row selection to work.
```tsx
import { DataGrid } from 'react-data-grid';
interface Row {
id: number;
name: string;
}
function rowKeyGetter(row: Row) {
return row.id;
}
function MyGrid() {
return <DataGrid columns={columns} rows={rows} rowKeyGetter={rowKeyGetter} />;
}
```
:bulb: While optional, setting this prop is recommended for optimal performance as the returned value is used to set the `key` prop on the row elements.
:warning: **Performance:** Define this function outside your component or memoize it with `useCallback` to prevent unnecessary re-renders.
###### `onRowsChange?: Maybe<(rows: R[], data: RowsChangeData<R, SR>) => void>`
Callback triggered when rows are changed.
The first parameter is a new rows array with both the updated rows and the other untouched rows.
The second parameter is an object with an `indexes` array highlighting which rows have changed by their index, and the `column` where the change happened.
```tsx
import { useState } from 'react';
import { DataGrid } from 'react-data-grid';
function MyGrid() {
const [rows, setRows] = useState(initialRows);
return <DataGrid columns={columns} rows={rows} onRowsChange={setRows} />;
}
```
###### `rowHeight?: Maybe<number | ((row: R) => number)>`
**Default:** `35` pixels
Height of each row in pixels. A function can be used to set different row heights.
```tsx
// Fixed height for all rows
<DataGrid columns={columns} rows={rows} rowHeight={50} />;
// Dynamic height per row
function getRowHeight(row) {
return row.isExpanded ? 100 : 35;
}
<DataGrid columns={columns} rows={rows} rowHeight={getRowHeight} />;
```
:warning: **Performance:** When using a function, the heights of all rows are processed upfront. For large datasets (1000+ rows), this can cause performance issues if the identity of the function changes and invalidates internal memoization. Consider using a static function when possible, or memoize the `rowHeight` function.
###### `headerRowHeight?: Maybe<number>`
**Default:** `rowHeight` when it is a number, otherwise `35` pixels
Height of the header row in pixels.
###### `summaryRowHeight?: Maybe<number>`
**Default:** `rowHeight` when it is a number, otherwise `35` pixels
Height of each summary row in pixels.
```tsx
<DataGrid
columns={columns}
rows={rows}
rowHeight={35}
headerRowHeight={45}
summaryRowHeight={40}
topSummaryRows={topSummaryRows}
/>
```
###### `columnWidths?: Maybe<ColumnWidths>`
A map of column widths containing both measured and resized widths. If not provided then an internal state is used.
```tsx
const [columnWidths, setColumnWidths] = useState((): ColumnWidths => new Map());
function addNewRow() {
setRows(...);
// reset column widths after adding a new row
setColumnWidths(new Map());
}
return <DataGrid columnWidths={columnWidths} onColumnWidthsChange={setColumnWidths} ... />
```
###### `onColumnWidthsChange?: Maybe<(columnWidths: ColumnWidths) => void>`
Callback triggered when column widths change. If not provided then an internal state is used.
###### `selectedRows?: Maybe<ReadonlySet<K>>`
A set of selected row keys. `rowKeyGetter` is required for row selection to work.
###### `isRowSelectionDisabled?: Maybe<(row: NoInfer<R>) => boolean>`
Function to determine if row selection is disabled for a specific row.
###### `onSelectedRowsChange?: Maybe<(selectedRows: Set<K>) => void>`
Callback triggered when the selection changes.
```tsx
import { useState } from 'react';
import { DataGrid, SelectColumn } from 'react-data-grid';
const rows: readonly Row[] = [...];
const columns: readonly Column<Row>[] = [
SelectColumn,
// other columns
];
function rowKeyGetter(row: Row) {
return row.id;
}
function isRowSelectionDisabled(row: Row) {
return !row.isActive;
}
function MyGrid() {
const [selectedRows, setSelectedRows] = useState((): ReadonlySet<number> => new Set());
return (
<DataGrid
rowKeyGetter={rowKeyGetter}
columns={columns}
rows={rows}
selectedRows={selectedRows}
isRowSelectionDisabled={isRowSelectionDisabled}
onSelectedRowsChange={setSelectedRows}
/>
);
}
```
###### `sortColumns?: Maybe<readonly SortColumn[]>`
An array of sorted columns.
Sorting is controlled: the grid does not reorder `rows` for you. Apply the sorting to your `rows` state (or derived rows) based on `sortColumns`.
###### `onSortColumnsChange?: Maybe<(sortColumns: SortColumn[]) => void>`
Callback triggered when sorting changes.
```tsx
import { useState } from 'react';
import { DataGrid, SelectColumn } from 'react-data-grid';
const rows: readonly Row[] = [...];
const columns: readonly Column<Row>[] = [
{
key: 'name',
name: 'Name',
sortable: true
},
// other columns
];
function MyGrid() {
const [sortColumns, setSortColumns] = useState<readonly SortColumn[]>([]);
return (
<DataGrid
columns={columns}
rows={rows}
sortColumns={sortColumns}
onSortColumnsChange={setSortColumns}
/>
);
}
```
More than one column can be sorted via `ctrl (command) + click`. To disable multiple column sorting, change the `onSortColumnsChange` function to
```tsx
function onSortColumnsChange(sortColumns: SortColumn[]) {
setSortColumns(sortColumns.slice(-1));
}
```
###### `defaultColumnOptions?: Maybe<DefaultColumnOptions<R, SR>>`
Default options applied to all columns.
```tsx
function MyGrid() {
return (
<DataGrid
columns={columns}
rows={rows}
defaultColumnOptions={{
minWidth: 100,
resizable: true,
sortable: true,
draggable: true
}}
/>
);
}
```
###### `onCellMouseDown?: CellMouseEventHandler<R, SR>`
Callback triggered when a pointer becomes active in a cell. The default behavior is to focus the cell. Call `preventGridDefault` to prevent the default behavior.
```tsx
function onCellMouseDown(args: CellMouseArgs<R, SR>, event: CellMouseEvent) {
if (args.column.key === 'id') {
event.preventGridDefault();
}
}
<DataGrid rows={rows} columns={columns} onCellMouseDown={onCellMouseDown} />;
```
###### `onCellClick?: CellMouseEventHandler<R, SR>`
Callback triggered when a cell is clicked.
```tsx
function onCellClick(args: CellMouseArgs<R, SR>, event: CellMouseEvent) {
if (args.column.key === 'id') {
event.preventGridDefault();
}
}
<DataGrid rows={rows} columns={columns} onCellClick={onCellClick} />;
```
This event can be used to open cell editor on single click
```tsx
function onCellClick(args: CellMouseArgs<R, SR>, event: CellMouseEvent) {
if (args.column.key === 'id') {
args.setActivePosition(true);
}
}
```
###### `onCellDoubleClick?: CellMouseEventHandler<R, SR>`
Callback triggered when a cell is double-clicked. The default behavior is to open the editor if the cell is editable. Call `preventGridDefault` to prevent the default behavior.
```tsx
function onCellDoubleClick(args: CellMouseArgs<R, SR>, event: CellMouseEvent) {
if (args.column.key === 'id') {
event.preventGridDefault();
}
}
<DataGrid rows={rows} columns={columns} onCellDoubleClick={onCellDoubleClick} />;
```
###### `onCellContextMenu?: CellMouseEventHandler<R, SR>`
Callback triggered when a cell is right-clicked.
```tsx
function onCellContextMenu(args: CellMouseArgs<R, SR>, event: CellMouseEvent) {
if (args.column.key === 'id') {
event.preventDefault();
// open custom context menu
}
}
<DataGrid rows={rows} columns={columns} onCellContextMenu={onCellContextMenu} />;
```
###### `onCellKeyDown?: Maybe<(args: CellKeyDownArgs<R, SR>, event: CellKeyboardEvent) => void>`
A function called when keydown event is triggered on a cell. This event can be used to customize cell navigation and editing behavior.
**Examples**
- Prevent editing on `Enter`
```tsx
function onCellKeyDown(args: CellKeyDownArgs<R, SR>, event: CellKeyboardEvent) {
if (args.mode === 'ACTIVE' && event.key === 'Enter') {
event.preventGridDefault();
}
}
```
- Prevent navigation on `Tab`
```tsx
function onCellKeyDown(args: CellKeyDownArgs<R, SR>, event: CellKeyboardEvent) {
if (args.mode === 'ACTIVE' && event.key === 'Tab') {
event.preventGridDefault();
}
}
```
Check [more examples](website/routes/CellNavigation.tsx)
###### `onCellCopy?: Maybe<(args: CellCopyArgs<NoInfer<R>, NoInfer<SR>>, event: CellClipboardEvent) => void>`
Callback triggered when a cell's content is copied.
###### `onCellPaste?: Maybe<(args: CellPasteArgs<NoInfer<R>, NoInfer<SR>>, event: CellClipboardEvent) => R>`
Callback triggered when content is pasted into a cell.
Return the updated row; the grid will call `onRowsChange` with it.
###### `onActivePositionChange?: Maybe<(args: PositionChangeArgs<R, SR>) => void>`
Triggered when the active position changes.
See the [`PositionChangeArgs`](#positionchangeargstrow-tsummaryrow) type in the Types section below.
###### `onFill?: Maybe<(event: FillEvent<R>) => R>`
###### `onScroll?: React.UIEventHandler<HTMLDivElement> | undefined`
Native DOM `onScroll` prop.
###### `onColumnResize?: Maybe<(column: CalculatedColumn<R, SR>, width: number) => void>`
Callback triggered when column is resized.
###### `onColumnsReorder?: Maybe<(sourceColumnKey: string, targetColumnKey: string) => void>`
Callback triggered when columns are reordered.
###### `enableVirtualization?: Maybe<boolean>`
**Default:** `true`
This prop can be used to disable virtualization.
###### `renderers?: Maybe<Renderers<R, SR>>`
Custom renderers for cells, rows, and other components.
See the [`Renderers`](#rendererstrow-tsummaryrow) type for the full shape.
Example of replacing default components:
```tsx
import { DataGrid, type Renderers } from 'react-data-grid';
const customRenderers: Renderers<Row, SummaryRow> = {
// Custom row render function
renderRow(key, props) {
return <CustomRow key={key} {...props} />;
},
// Custom cell render function
renderCell(key, props) {
return <CustomCell key={key} {...props} />;
},
// Custom checkbox render function
renderCheckbox(props) {
return <CustomCheckbox {...props} />;
},
// Custom sort status indicator
renderSortStatus(props) {
return <CustomSortIcon {...props} />;
},
// Custom empty state
noRowsFallback: <div>No data available</div>
};
<DataGrid columns={columns} rows={rows} renderers={customRenderers} />;
```
The default `<Row />` component can be wrapped via the `renderRow` prop to add contexts or tweak props:
```tsx
import { DataGrid, Row, type RenderRowProps } from 'react-data-grid';
interface MyRow {
id: number;
}
function myRowRenderer(key: React.Key, props: RenderRowProps<MyRow>) {
return (
<MyContext key={key} value={123}>
<Row {...props} />
</MyContext>
);
}
function MyGrid() {
return <DataGrid columns={columns} rows={rows} renderers={{ renderRow: myRowRenderer }} />;
}
```
###### `rowClass?: Maybe<(row: R, rowIdx: number) => Maybe<string>>`
Function to apply custom class names to rows.
```tsx
import { DataGrid } from 'react-data-grid';
function rowClass(row: Row, rowIdx: number) {
return rowIdx % 2 === 0 ? 'even' : 'odd';
}
function MyGrid() {
return <DataGrid columns={columns} rows={rows} rowClass={rowClass} />;
}
```
:warning: **Performance:** Define this function outside your component or memoize it with `useCallback` to avoid re-rendering all rows on every render.
###### `headerRowClass?: Maybe<string>`
Custom class name for the header row.
```tsx
<DataGrid columns={columns} rows={rows} headerRowClass="sticky-header" />
```
###### `direction?: Maybe<'ltr' | 'rtl'>`
This property sets the text direction of the grid, it defaults to `'ltr'` (left-to-right). Setting `direction` to `'rtl'` has the following effects:
- Columns flow from right to left
- Start-frozen columns are pinned on the right, and end-frozen columns are pinned on the left
- Column resize cursor is shown on the left edge of the column
- Scrollbar is moved to the left
###### `className?: string | undefined`
Custom class name for the grid.
###### `style?: CSSProperties | undefined`
Custom styles for the grid.
###### `role?: string | undefined`
ARIA role for the grid container. Defaults to `grid`.
###### `'aria-label'?: string | undefined`
The label of the grid. We recommend providing a label using `aria-label` or `aria-labelledby`
###### `'aria-labelledby'?: string | undefined`
The id of the element containing a label for the grid. We recommend providing a label using `aria-label` or `aria-labelledby`
###### `'aria-rowcount'?: number | undefined`
Total number of rows for assistive technologies.
###### `'aria-description'?: string | undefined`
###### `'aria-describedby'?: string | undefined`
If the grid has a caption or description, `aria-describedby` can be set on the grid element with a value referring to the element containing the description.
###### `'data-testid'?: Maybe<string>`
This prop can be used to add a testid for testing. We recommend querying the grid by its `role` and `name`.
```tsx
function MyGrid() {
return <DataGrid aria-label="my-grid" columns={columns} rows={rows} />;
}
test('grid', async () => {
await page.render(<MyGrid />);
const grid = page.getByRole('grid', { name: 'my-grid' });
});
```
###### `'data-cy'?: Maybe<string>`
Optional attribute to help with Cypress (or similar) selectors.
#### `<TreeDataGrid />`
`TreeDataGrid` is a component built on top of `DataGrid` to add hierarchical row grouping. This implements the [Treegrid pattern](https://www.w3.org/WAI/ARIA/apg/patterns/treegrid/).
**How it works:**
1. The `groupBy` prop specifies which columns should be used for grouping
2. The `rowGrouper` function groups rows by the specified column keys
3. Group rows are rendered with expand/collapse toggles
4. Child rows are nested under their parent groups
5. Groups can be expanded/collapsed by clicking the toggle or using keyboard navigation (<kbd>←</kbd>, <kbd>→</kbd>)
**Keyboard Navigation:**
- <kbd>→</kbd> (Right Arrow): Expand a collapsed group row when focused
- <kbd>←</kbd> (Left Arrow): Collapse an expanded group row when focused, or navigate to parent group
**Unsupported Props:**
The following `DataGrid` props are not supported in `TreeDataGrid`:
- `onFill` - Drag-fill is disabled for tree grids
- `isRowSelectionDisabled` - Row selection disabling is not available
- `role` - `TreeDataGrid` manages the ARIA role
- `aria-rowcount` - `TreeDataGrid` manages the ARIA row count
**Caveats:**
- Group columns cannot be rendered under one column
- Group columns are automatically frozen and cannot be unfrozen
- Cell copy/paste does not work on group rows
- Column groups are not supported; `columns` must be `Column[]`
##### TreeDataGridProps
All [`DataGridProps`](#datagridprops) are supported except those listed above. The `columns` prop only supports `Column[]` (no column groups). When `rowHeight` is a function, it receives [`RowHeightArgs`](#rowheightargstrow) instead of just the row. Additional props are listed below:
###### `groupBy: readonly string[]`
**Required.** An array of column keys to group by. The order determines the grouping hierarchy (first key is the top level, second key is nested under the first, etc.).
```tsx
import { TreeDataGrid, type Column } from 'react-data-grid';
interface Row {
id: number;
country: string;
city: string;
name: string;
}
const columns: readonly Column<Row>[] = [
{ key: 'country', name: 'Country' },
{ key: 'city', name: 'City' },
{ key: 'name', name: 'Name' }
];
function MyGrid() {
return (
<TreeDataGrid
columns={columns}
rows={rows}
groupBy={['country', 'city']}
// ... other props
/>
);
}
```
###### `rowGrouper: (rows: readonly R[], columnKey: string) => Record<string, readonly R[]>`
**Required.** A function that groups rows by the specified column key. Returns an object where keys are the group values and values are arrays of rows belonging to that group.
```tsx
function rowGrouper(rows: readonly Row[], columnKey: string): Record<string, readonly Row[]> {
return Object.groupBy(rows, (row) => row[columnKey]);
}
```
###### `expandedGroupIds: ReadonlySet<unknown>`
**Required.** A set of group IDs that are currently expanded. Group IDs are generated by `groupIdGetter`.
```tsx
import { useState } from 'react';
import { TreeDataGrid } from 'react-data-grid';
function MyGrid() {
const [expandedGroupIds, setExpandedGroupIds] = useState((): ReadonlySet<unknown> => new Set());
return (
<TreeDataGrid
expandedGroupIds={expandedGroupIds}
onExpandedGroupIdsChange={setExpandedGroupIds}
// ... other props
/>
);
}
```
###### `onExpandedGroupIdsChange: (expandedGroupIds: Set<unknown>) => void`
**Required.** Callback triggered when groups are expanded or collapsed.
###### `groupIdGetter?: Maybe<(groupKey: string, parentId?: string) => string>`
Function to generate unique IDs for group rows. If not provided, a default implementation is used that concatenates parent and group keys with `__`.
###### `rowHeight?: Maybe<number | ((args: RowHeightArgs<R>) => number)>`
**Note:** Unlike `DataGrid`, the `rowHeight` function receives [`RowHeightArgs<R>`](#rowheightargstrow) which includes a `type` property to distinguish between regular rows and group rows:
```tsx
function getRowHeight(args: RowHeightArgs<Row>): number {
if (args.type === 'GROUP') {
return 50; // Custom height for group rows
}
return 35; // Height for regular rows
}
<TreeDataGrid rowHeight={getRowHeight} ... />
```
#### `<Row />`
The default row component. Can be wrapped via the `renderers.renderRow` prop.
##### Props
[`RenderRowProps<TRow, TSummaryRow>`](#renderrowpropstrow-tsummaryrow)
#### `<Cell />`
The default cell component. Can be wrapped via the `renderers.renderCell` prop.
##### Props
[`CellRendererProps<TRow, TSummaryRow>`](#cellrendererpropstrow-tsummaryrow)
#### `<SelectCellFormatter />`
A formatter component for rendering row selection checkboxes.
##### Props
###### `value: boolean`
Whether the checkbox is checked.
###### `tabIndex?: number | undefined`
The tab index for keyboard navigation.
###### `indeterminate?: boolean | undefined`
Whether the checkbox is in an indeterminate state.
###### `disabled?: boolean | undefined`
Whether the checkbox is disabled.
###### `onChange: (checked: boolean, shift: boolean) => void`
Callback when the checkbox state changes.
###### `'aria-label'?: string | undefined`
Accessible label for the checkbox.
###### `'aria-labelledby'?: string | undefined`
ID of the element that labels the checkbox.
#### `<ToggleGroup />`
Low-level component used by `renderToggleGroup` to render the expand/collapse control. Useful if you build a custom group cell renderer.
### Hooks
#### `useHeaderRowSelection()`
Hook for managing header row selection state. Used within custom header cell renderers to implement custom "select all" functionality.
**Returns:**
- `isIndeterminate: boolean` - Whether some (but not all) rows are selected
- `isRowSelected: boolean` - Whether all rows are selected
- `onRowSelectionChange: (event: SelectHeaderRowEvent) => void` - Callback to change selection state
**Example:**
```tsx
import { useLayoutEffect, useRef } from 'react';
function CustomHeaderCell() {
const { isIndeterminate, isRowSelected, onRowSelectionChange } = useHeaderRowSelection();
const checkboxRef = useRef<HTMLInputElement>(null);
useLayoutEffect(() => {
if (checkboxRef.current) {
checkboxRef.current.indeterminate = isIndeterminate && !isRowSelected;
}
}, [isIndeterminate, isRowSelected]);
return (
<input
ref={checkboxRef}
type="checkbox"
checked={isRowSelected}
onChange={(event) => onRowSelectionChange({ checked: event.target.checked })}
/>
);
}
```
#### `useRowSelection()`
Hook for managing row selection state. Used within custom cell renderers to implement custom row selection.
**Returns:**
- `isRowSelectionDisabled: boolean` - Whether selection is disabled for this row
- `isRowSelected: boolean` - Whether this row is selected
- `onRowSelectionChange: (event: SelectRowEvent<R>) => void` - Callback to change selection state
**Example:**
```tsx
function CustomSelectCell({ row }: RenderCellProps<Row>) {
const { isRowSelectionDisabled, isRowSelected, onRowSelectionChange } = useRowSelection();
return (
<input
type="checkbox"
disabled={isRowSelectionDisabled}
checked={isRowSelected}
onChange={(event) =>
onRowSelectionChange({
row,
checked: event.currentTarget.checked,
isShiftClick: event.nativeEvent.shiftKey
})
}
/>
);
}
```
### Render Functions
#### `renderHeaderCell<R, SR>(props: RenderHeaderCellProps<R, SR>)`
The default header cell renderer. Renders sortable columns with sort indicators.
**Example:**
```tsx
import { renderHeaderCell, type Column } from 'react-data-grid';
const columns: readonly Column<Row>[] = [
{
key: 'name',
name: 'Name',
sortable: true,
renderHeaderCell
}
];
```
#### `renderTextEditor<TRow, TSummaryRow>(props: RenderEditCellProps<TRow, TSummaryRow>)`
A basic text editor provided for convenience.
**Example:**
```tsx
import { renderTextEditor, type Column } from 'react-data-grid';
const columns: readonly Column<Row>[] = [
{
key: 'title',
name: 'Title',
renderEditCell: renderTextEditor
}
];
```
#### `renderSortIcon(props: RenderSortIconProps)`
Renders the sort direction arrow icon.
**Props:**
- `sortDirection: SortDirection | undefined` - 'ASC', 'DESC', or undefined
#### `renderSortPriority(props: RenderSortPriorityProps)`
Renders the sort priority number for multi-column sorting.
**Props:**
- `priority: number | undefined` - The sort priority (1, 2, 3, etc.)
#### `renderCheckbox(props: RenderCheckboxProps)`
Renders a checkbox input with proper styling and accessibility.
**Props:**
- `checked: boolean` - Whether the checkbox is checked
- `indeterminate?: boolean` - Whether the checkbox is in indeterminate state
- `disabled?: boolean` - Whether the checkbox is disabled
- `onChange: (checked: boolean, shift: boolean) => void` - Change handler
- `tabIndex: number` - Tab index for keyboard navigation
- `aria-label?: string` - Accessible label
- `aria-labelledby?: string` - ID of labeling element
**Example:**
```tsx
import { DataGrid, renderCheckbox } from 'react-data-grid';
<DataGrid
renderers={{
renderCheckbox: (props) => renderCheckbox({ ...props, 'aria-label': 'Select row' })
}}
/>;
```
#### `renderToggleGroup<R, SR>(props: RenderGroupCellProps<R, SR>)`
The default group cell renderer used by the columns used for grouping (`groupBy` prop). This renders the expand/collapse toggle.
##### Props
[`RenderGroupCellProps<TRow, TSummaryRow>`](#rendergroupcellpropstrow-tsummaryrow)
**Example:**
```tsx
import { renderToggleGroup, type Column } from 'react-data-grid';
const columns: readonly Column<Row>[] = [
{
key: 'group',
name: 'Group',
renderGroupCell: renderToggleGroup
}
];
```
#### `renderValue<R, SR>(props: RenderCellProps<R, SR>)`
The default cell renderer that renders the value of `row[column.key]`.
**Example:**
```tsx
import { renderValue, type Column } from 'react-data-grid';
const columns: readonly Column<Row>[] = [
{
key: 'title',
name: 'Title',
renderCell: renderValue
}
];
```
### Context
#### `DataGridDefaultRenderersContext`
Context for providing default renderers to DataGrids in your app.
**Example:**
```tsx
import {
DataGridDefaultRenderersContext,
renderCheckbox,
renderSortIcon,
renderSortPriority,
type Renderers
} from 'react-data-grid';
// custom implementations of renderers
const defaultGridRenderers: Renderers<unknown, unknown> = {
renderCheckbox,
renderSortStatus(props) {
return (
<>
{renderSortIcon(props)}
{renderSortPriority(props)}
</>
);
}
};
function AppProvider({ children }) {
return (
<DataGridDefaultRenderersContext value={defaultGridRenderers}>
{children}
</DataGridDefaultRenderersContext>
);
}
```
### Other
#### `SelectColumn: Column<any, any>`
A pre-configured column for row selection.
Includes checkbox renderers for header, regular rows, and grouped rows.
**Example:**
```tsx
import { DataGrid, SelectColumn, type Column } from 'react-data-grid';
const columns: readonly Column<Row>[] = [SelectColumn, ...otherColumns];
function rowKeyGetter(row: Row) {
return row.id;
}
function MyGrid() {
return (
<DataGrid
columns={columns}
rows={rows}
rowKeyGetter={rowKeyGetter}
selectedRows={selectedRows}
onSelectedRowsChange={setSelectedRows}
/>
);
}
```
#### `SELECT_COLUMN_KEY = 'rdg-select-column'`
The key used for the `SelectColumn`. Useful for identifying or filtering the select column.
**Example:**
```tsx
import { SELECT_COLUMN_KEY } from 'react-data-grid';
const nonSelectColumns = columns.filter((column) => column.key !== SELECT_COLUMN_KEY);
```
### Types
#### `Column<TRow, TSummaryRow>`
Defines the configuration for a column in the grid.
##### `name: string | ReactElement`
The name of the column. Displayed in the header cell by default.
##### `key: string`
A unique key to distinguish each column
##### `width?: Maybe<number | string>`
**Default** `auto`
Width can be any valid css grid column value. If not specified, it will be determined automatically based on grid width and specified widths of other columns.
```tsx
const columns: Column<Row>[] = [
{
key: 'id',
name: 'ID',
width: 80, // Fixed width in pixels
resizable: false
},
{
key: 'name',
name: 'Name',
width: '30%', // Percentage width
minWidth: 100,
maxWidth: 400
},
{
key: 'description',
name: 'Description'
// No width specified - automatically sized
}
];
```
Other examples:
```tsx
width: 80, // pixels
width: '25%',
width: 'max-content',
width: 'minmax(100px, max-content)',
```
`max-content` can be used to expand the column to show all the content. Note that the grid is only able to calculate column width for visible rows.
##### `minWidth?: Maybe<number>`
**Default**: `50` pixels
Minimum column width in pixels.
##### `maxWidth?: Maybe<number>`
Maximum column width in pixels.
##### `cellClass?: Maybe<string | ((row: TRow) => Maybe<string>)>`
Class name(s) for cells. Can be a string or a function that returns a class name based on the row.
```tsx
const columns: Column<Row>[] = [
{
key: 'status',
name: 'Status',
cellClass: (row) => `status-${row.status}`
},
{
key: 'price',
name: 'Price',
cellClass: 'text-right' // Static class
}
];
```
```css
.status-active {
color: green;
font-weight: bold;
}
.status-inactive {
color: grey;
}
.text-right {
text-align: right;
}
```
##### `headerCellClass?: Maybe<string>`
Class name(s) for the header cell.
##### `summaryCellClass?: Maybe<string | ((row: TSummaryRow) => Maybe<string>)>`
Class name(s) for summary cells. Can be a string or a function that returns a class name based on the summary row.
##### `renderCell?: Maybe<(props: RenderCellProps<TRow, TSummaryRow>) => ReactNode>`
Render function to render the content of cells.
##### `renderHeaderCell?: Maybe<(props: RenderHeaderCellProps<TRow, TSummaryRow>) => ReactNode>`
Render function to render the content of the header cell.
##### `renderSummaryCell?: Maybe<(props: RenderSummaryCellProps<TSummaryRow, TRow>) => ReactNode>`
Render function to render the content of summary cells
##### `renderGroupCell?: Maybe<(props: RenderGroupCellProps<TRow, TSummaryRow>) => ReactNode>`
Render function to render the content of group cells when using `TreeDataGrid`.
##### `renderEditCell?: Maybe<(props: RenderEditCellProps<TRow, TSummaryRow>) => ReactNode>`
Render function to render the content of edit cells. When set, the column is automatically set to be editable
##### `editable?: Maybe<boolean | ((row: TRow) => boolean)>`
Control whether cells can be edited with `renderEditCell`.
##### `colSpan?: Maybe<(args: ColSpanArgs<TRow, TSummaryRow>) => Maybe<number>>`
Function to determine how many columns this cell should span. Returns the number of columns to span, or `undefined` for no spanning. See the [`ColSpanArgs`](#colspanargstrow-tsummaryrow) type in the Types section below.
**Example:**
```tsx
import type { Column } from 'react-data-grid';
const columns: readonly Column<Row>[] = [
{
key: 'title',
name: 'Title',
colSpan(args) {
if (args.type === 'ROW' && args.row.isFullWidth) {
return 5; // Span 5 columns for full-width rows
}
return undefined;
}
}
];
```
##### `frozen?: Maybe<boolean | 'start' | 'end'>`
**Default**: `false`
Determines whether the column is frozen, and on which edge. Frozen columns stay in place when the grid is scrolled horizontally.
- `'start'` (or `true` for backwards compatibility) — pins the column to the start edge (left in LTR, right in RTL).
- `'end'` — pins the column to the end edge (right in LTR, left in RTL).
- `false` (default) — the column scrolls with the rest of the grid.
```tsx
const columns: readonly Column<Row>[] = [
{ key: 'id', name: 'ID', frozen: 'start' },
{ key: 'name', name: 'Name' },
{ key: 'actions', name: 'Actions', frozen: 'end' }
];
```
##### `resizable?: Maybe<boolean>`
**Default**: `false`
Enable resizing of the column
##### `sortable?: Maybe<boolean>`
**Default**: `false`
Enable sorting of the column
##### `draggable?: Maybe<boolean>`
**Default**: `false`
Enable dragging of the column
##### `sortDescendingFirst?: Maybe<boolean>`
**Default**: `false`
Sets the column sort order to be descending instead of ascending the first time the column is sorted
##### `editorOptions`
Options for cell editing.
###### `displayCellContent?: Maybe<boolean>`
**Default**: `false`
Render the cell content in addition to the edit cell content. Enable this option when the editor is rendered outside the grid, like a modal for example.
###### `commitOnOutsideClick?: Maybe<boolean>`
**Default**: `true`
Commit changes when clicking outside the cell.
###### `closeOnExternalRowChange?: Maybe<boolean>`
**Default**: `true`
Close the editor when the row value changes externally.
#### `ColumnGroup<TRow, TSummaryRow>`
Defines a group of columns that share a common header.
```tsx
interface ColumnGroup<R, SR = unknown> {
readonly name: string | ReactElement;
readonly headerCellClass?: Maybe<string>;
readonly children: readonly ColumnOrColumnGroup<R, SR>[];
}
```
**Example:**
```tsx
import type { ColumnOrColumnGroup } from 'react-data-grid';
const columns: readonly ColumnOrColumnGroup<Row>[] = [
{
name: 'Personal Info',
children: [
{ key: 'firstName', name: 'First Name' },
{ key: 'lastName', name: 'Last Name' }
]
}
];
```
#### `ColumnOrColumnGroup<TRow, TSummaryRow>`
Union type representing either a `Column` or a `ColumnGroup`.
#### `CalculatedColumn<TRow, TSummaryRow>`
Extends `Column` with additional computed properties used internally by the grid. This is the type passed to render functions.
**Additional properties:**
- `idx: number` - The column index
- `level: number` - Nesting level when using column groups
- `parent: CalculatedColumnParent | undefined` - Parent column group if nested
- Multiple Column properties have their values set to their default value
#### `CalculatedColumnParent<TRow, TSummaryRow>`
Represents a parent column group in the calculated column structure.
```tsx
interface CalculatedColumnParent<R, SR> {
readonly name: string | ReactElement;
readonly parent: CalculatedColumnParent<R, SR> | undefined;
readonly idx: number;
readonly colSpan: number;
readonly level: number;
readonly headerCellClass?: Maybe<string>;
}
```
#### `CalculatedColumnOrColumnGroup<TRow, TSummaryRow>`
Union type representing either a `CalculatedColumnParent` or a `CalculatedColumn`.
```tsx
type CalculatedColumnOrColumnGroup<R, SR> = CalculatedColumnParent<R, SR> | CalculatedColumn<R, SR>;
```
#### `RowHeightArgs<TRow>`
Arguments passed to `TreeDataGrid`'s `rowHeight` prop when it is a function.
```tsx
type RowHeightArgs<TRow> = { type: 'ROW'; row: TRow } | { type: 'GROUP'; row: GroupRow<TRow> };
```
**Example:**
```tsx
function getRowHeight(args: RowHeightArgs<Row>): number {
if (args.type === 'GROUP') {
return 40;
}
return args.row.isLarge ? 60 : 35;
}
<TreeDataGrid rowHeight={getRowHeight} ... />
```
#### `RenderCellProps<TRow, TSummaryRow>`
Props passed to custom cell renderers.
```tsx
interface RenderCellProps<TRow, TSummaryRow = unknown> {
column: CalculatedColumn<TRow, TSummaryRow>;
row: TRow;
rowIdx: number;
isCellEditable: boolean;
tabIndex: number;
onRowChange: (row: TRow) => void;
}
```
**Example:**
```tsx
import type { RenderCellProps } from 'react-data-grid';
function renderCell({ row, column, onRowChange }: RenderCellProps<MyRow>) {
return (
<div>
{row[column.key]}
<button onClick={() => onRowChange({ ...row, updated: true })}>Update</button>
</div>
);
}
```
#### `RenderHeaderCellProps<TRow, TSummaryRow>`
Props passed to custom header cell renderers.
```tsx
interface RenderHeaderCellProps<TRow, TSummaryRow = unknown> {
column: CalculatedColumn<TRow, TSummaryRow>;
sortDirection: SortDirection | undefined;
priority: number | undefined;
tabIndex: number;
}
```
#### `RenderEditCellProps<TRow, TSummaryRow>`
Props passed to custom edit cell renderers (editors).
```tsx
interface RenderEditCellProps<TRow, TSummaryRow = unknown> {
column: CalculatedColumn<TRow, TSummaryRow>;
row: TRow;
rowIdx: number;
onRowChange: (row: TRow, commitChanges?: boolean) => void;
onClose: (commitChanges?: boolean, shouldFocus?: boolean) => void;
}
```
**Example:**
```tsx
import type { RenderEditCellProps } from 'react-data-grid';
function CustomEditor({ row, column, onRowChange, onClose }: RenderEditCellProps<MyRow>) {
return (
<input
autoFocus
value={row[column.key]}
onChange={(event) => onRowChange({ ...row, [column.key]: event.target.value })}
onBlur={() => onClose(true)}
/>
);
}
```
#### `RenderSummaryCellProps<TSummaryRow, TRow>`
Props passed to summary cell renderers.
```tsx
interface RenderSummaryCellProps<TSummaryRow, TRow = unknown> {
column: CalculatedColumn<TRow, TSummaryRow>;
row: TSummaryRow;
tabIndex: number;
}
```
#### `RenderGroupCellProps<TRow, TSummaryRow>`
Props passed to group cell renderers when using `TreeDataGrid`.
```tsx
interface RenderGroupCellProps<TRow, TSummaryRow = unknown> {
groupKey: unknown;
column: CalculatedColumn<TRow, TSummaryRow>;
row: GroupRow<TRow>;
childRows: readonly TRow[];
isExpanded: boolean;
tabIndex: number;
toggleGroup: () => void;
}
```
#### `RenderRowProps<TRow, TSummaryRow>`
Props passed to custom row renderers.
```tsx
interface RenderRowProps<TRow, TSummaryRow = unknown> {
row: TRow;
iterateOverViewportColumnsForRow: IterateOverViewportColumnsForRow<TRow, TSummaryRow>;
rowIdx: number;
activeCellIdx: number | undefined;
isRowSelectionDisabled: boolean;
isRowSelected: boolean;
gridRowStart: number;
draggedOverCellIdx: number | undefined;
activeCellEditor: ReactElement<RenderEditCellProps<TRow>> | undefined;
onRowChange: (column: CalculatedColumn<TRow, TSummaryRow>, rowIdx: number, newRow: TRow) => void;
rowClass: Maybe<(row: TRow, rowIdx: number) => Maybe<string>>;
isTreeGrid: boolean;
// ... and event handlers
}
```
#### `CellRendererProps<TRow, TSummaryRow>`
Props passed to the cell renderer when using `renderers.renderCell`.
Shares a base type with row render props (DOM props and cell event handlers) but only includes cell-specific fields like `column`, `row`, `rowIdx`, `colSpan`, and position state.
#### `Renderers<TRow, TSummaryRow>`
Custom renderer configuration for the grid.
```tsx
interface Renderers<TRow, TSummaryRow> {
renderCell?: Maybe<(key: Key, props: CellRendererProps<TRow, TSummaryRow>) => ReactNode>;
renderCheckbox?: Maybe<(props: RenderCheckboxProps) => ReactNode>;
renderRow?: Maybe<(key: Key, props: RenderRowProps<TRow, TSummaryRow>) => ReactNode>;
renderSortStatus?: Maybe<(props: RenderSortStatusProps) => ReactNode>;
noRowsFallback?: Maybe<ReactNode>;
}
```
#### `CellMouseArgs<TRow, TSummaryRow>`
Arguments passed to cell mouse event handlers.
```tsx
interface CellMouseArgs<TRow, TSummaryRow = unknown> {
/** The column object of the cell. */
column: CalculatedColumn<TRow, TSummaryRow>;
/** The row object of the cell. */
row: TRow;
/** The row index of the cell. */
rowIdx: number;
/** Function to manually focus the cell. Pass `true` to immediately start editing. */
setActivePosition: (enableEditor?: boolean) => void;
}
```
**Example:**
```tsx
import type { CellMouseArgs, CellMouseEvent } from 'react-data-grid';
function onCellClick(args: CellMouseArgs<Row>, event: CellMouseEvent) {
console.log('Clicked cell at row', args.rowIdx, 'column', args.column.key);
args.setActivePosition(true); // Focus and start editing
}
```
#### `CellMouseEventHandler<TRow, TSummaryRow>` (internal)
Handler type used by `onCellMouseDown`, `onCellClick`, `onCellDoubleClick`, and `onCellContextMenu`. This helper type is not exported; the shape is shown for reference.
```tsx
type CellMouseEventHandler<TRow, TSummaryRow> = Maybe<
(args: CellMouseArgs<TRow, TSummaryRow>, event: CellMouseEvent) => void
>;
```
#### `CellMouseEvent`
Extends `React.MouseEvent<HTMLDivElement>` with grid-specific methods.
##### `event.preventGridDefault(): void`
Prevents the default grid behavior for this event.
##### `event.isGridDefaultPrevented(): boolean`
Returns whether `preventGridDefault` was called.
**Example:**
```tsx
import type { CellMouseArgs, CellMouseEvent } from 'react-data-grid';
function onCellClick(args: CellMouseArgs<Row>, event: CellMouseEvent) {
if (args.column.key === 'actions') {
event.preventGridDefault(); // Prevent cell focus
}
}
```
#### `CellKeyboardEvent`
Extends `React.KeyboardEvent<HTMLDivElement>` with grid-specific methods.
##### `event.preventGridDefault(): void`
Prevents the default grid behavior for this keyboard event.
##### `event.isGridDefaultPrevented(): boolean`
Returns whether `preventGridDefault` was called.
#### `CellClipboardEvent`
Type alias for `React.ClipboardEvent<HTMLDivElement>`. Used for copy and paste events.
```tsx
type CellClipboardEvent = React.ClipboardEvent<HTMLDivElement>;
```
#### `CellKeyDownArgs<TRow, TSummaryRow>`
Arguments passed to the `onCellKeyDown` handler. The shape differs based on whether the cell is in ACTIVE or EDIT mode.
**ACTIVE mode:**
```tsx
interface ActiveCellKeyDownArgs<TRow, TSummaryRow = unknown> {
mode: 'ACTIVE';
column: CalculatedColumn<TRow, TSummaryRow> | undefined;
row: TRow | undefined;
rowIdx: number;
setActivePosition: (position: Position, options?: SetActivePositionOptions) => void;
}
```
**EDIT mode:**
```tsx
interface EditCellKeyDownArgs<TRow, TSummaryRow = unknown> {
mode: 'EDIT';
column: CalculatedColumn<TRow, TSummaryRow>;
row: TRow;
rowIdx: number;
navigate: () => void;
onClose: (commitChanges?: boolean, shouldFocus?: boolean) => void;
}
```
**Example:**
```tsx
import type { CellKeyboardEvent, CellKeyDownArgs