diff --git a/README.md b/README.md index f1d8cdb50e..c978c9765e 100644 --- a/README.md +++ b/README.md @@ -596,20 +596,124 @@ test('grid', async () => { #### `` -`TreeDataGrid` is component built on top of `DataGrid` to add row grouping. This implements the [Treegrid pattern](https://www.w3.org/WAI/ARIA/apg/patterns/treegrid/). At the moment `TreeDataGrid` does not support `onFill` and `isRowSelectionDisabled` props +`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 (, ) + +**Keyboard Navigation:** + +- (Right Arrow): Expand a collapsed group row when focused +- (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 + +**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 ##### TreeDataGridProps -###### `groupBy?: Maybe` +All [`DataGridProps`](#datagridprops) are supported except those listed above, plus the following additional props: + +###### `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[] = [ + { key: 'country', name: 'Country' }, + { key: 'city', name: 'City' }, + { key: 'name', name: 'Name' } +]; -###### `rowGrouper?: Maybe<(rows: readonly R[], columnKey: string) => Record>` +function MyGrid() { + return ( + + ); +} +``` -###### `expandedGroupIds?: Maybe>` +###### `rowGrouper: (rows: readonly R[], columnKey: string) => Record` -###### `onExpandedGroupIdsChange?: Maybe<(expandedGroupIds: Set) => void>` +**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: Row[], columnKey: string) { + return Object.groupBy(rows, (row) => row[columnKey]); +} +``` + +###### `expandedGroupIds: ReadonlySet` + +**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 => new Set()); + + return ( + + ); +} +``` + +###### `onExpandedGroupIdsChange: (expandedGroupIds: Set) => 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)>` + +**Note:** Unlike `DataGrid`, the `rowHeight` function receives [`RowHeightArgs`](#rowheightargstrow) which includes a `type` property to distinguish between regular rows and group rows: + +```tsx +function getRowHeight(args: RowHeightArgs): number { + if (args.type === 'GROUP') { + return 50; // Custom height for group rows + } + return 35; // Height for regular rows +} + + +``` + #### `` The default row component. Can be wrapped via the `renderers.renderRow` prop.