# Data Grid URL: /docs/web/components/data-grid A virtualized, editable spreadsheet-like data grid with sorting, filtering, grouping, cell selection, and keyboard navigation. **Demo:** ```tsx 'use client'; // @custom-demo import { useCallback, useMemo, useState } from 'react'; import { DataGrid, DataGridDisplayMenu, DataGridFilterMenu, DataGridGroupMenu, DataGridKeyboardShortcuts, DataGridRowHeightMenu, DataGridSortMenu, DataGridViewMenu, type ColumnDef, type RowChange, getDataGridActionsColumn, getDataGridSelectColumn, useDataGrid } from '@docyrus/ui/components/data-grid'; import { SearchInput } from '@docyrus/ui/components/search-input'; import { useMounted } from '@docyrus/ui/primitives/hooks/use-mounted'; import { Button } from '@docyrus/ui/primitives/ui/button'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from '@docyrus/ui/primitives/ui/dropdown-menu'; import { TooltipProvider } from '@docyrus/ui/primitives/ui/tooltip'; import { cn } from '@docyrus/ui/primitives/lib/utils'; import { DocyrusIcon } from '@docyrus/ui/components/docyrus-icon'; import { Copy, MoreHorizontal, Pencil, Trash2 } from 'lucide-react'; import { PropControls } from '@/components/prop-controls'; import { useDemoData } from '@/data/data-grid-data'; function DataGridDemoInner() { const { data, columns: columnDefs, props: extraProps, controls } = useDemoData(); const [open, setOpen] = useState(false); const [keyword, setKeyword] = useState(''); type Row = typeof data[number]; const actionColumn = useMemo ) }), [extraProps] ); const columns = [getDataGridSelectColumn ); } ``` ## Installation ```bash pnpm dlx @docyrus/cli add @docyrus/ui-data-grid ``` **Dependencies:** - [lucide-react](https://www.npmjs.com/package/lucide-react) - [sonner](https://www.npmjs.com/package/sonner) - [@tanstack/react-table](https://www.npmjs.com/package/@tanstack/react-table) - [@radix-ui/react-direction](https://www.npmjs.com/package/@radix-ui/react-direction) - [@types/react](https://www.npmjs.com/package/@types/react) - [@tanstack/react-virtual](https://www.npmjs.com/package/@tanstack/react-virtual) ## Usage ```tsx 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 ) }); const columns = [ getDataGridSelectColumn ) }); ``` ### 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. ```tsx const actions: DataGridAction ``` ## 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. ```tsx 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 ) }); const columns = [getDataGridSelectColumn(), actionColumn, ...yourColumns]; ``` | Option | Type | Default | Description | |--------|------|---------|-------------| | `actionCount` | `number` | `2` | Number of inline action buttons. Used to auto-calculate column width when `size` is not provided. | | `visibleOnHover` | `boolean` | `true` | Hide cell content until row hover on non-touch screens. Uses CSS `@media (hover: hover)` with `transition-opacity`. | | `size` | `number` | auto | Column width in pixels. If omitted, calculated as `actionCount × 28 + (actionCount − 1) × 2 + 12`. | | `enableHiding` | `boolean` | `false` | Whether the column can be hidden via view menu | | `enableResizing` | `boolean` | `false` | Whether the column width can be resized | | `enableSorting` | `boolean` | `false` | Whether 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. ```tsx { accessorKey: string; header: string | (() => ReactNode); size?: number; meta?: { label?: string; group?: string; cell?: CellOpts; visibleOnHover?: boolean; format?: (value: TValue, row: TData) => string; }; } ``` | Meta Field | Type | Description | |------------|------|-------------| | `label` | `string` | Display name used in menus, change tracking popover, and filter/sort/group UIs | | `group` | `string` | Column grouping category | | `cell` | `CellOpts` | Cell variant and its configuration | | `visibleOnHover` | `boolean` | Hide cell content until row hover on non-touch screens | | `format` | `(value: TValue, row: TData) => string` | Custom formatter for cell display and export | ### CellOpts A discriminated union defining the cell variant and its configuration. Set via `meta.cell` on column definitions. | Variant | Additional Props | Data Type | Description | |---------|-----------------|-----------|-------------| | `short-text` | — | `string` | Single-line text input | | `long-text` | — | `string` | Multi-line text with expand | | `email` | — | `string` | Email with mailto link | | `phone` | — | `string` | Phone number with tel link | | `number` | `min?`, `max?`, `step?`, `decimalPrecision?`, `thousandSeparator?` | `number` | Numeric 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. | | `currency` | `currency?`, `min?`, `max?`, `step?`, `decimalPrecision?`, `thousandSeparator?` | `number` | Formatted currency value. Precision/grouping overrides override the locale defaults. | | `percent` | `min?`, `max?`, `step?`, `decimalPrecision?`, `thousandSeparator?` | `number` | Percentage display (0-1 range). | | `url` | — | `string` | Clickable URL link | | `checkbox` | — | `boolean` | Boolean checkbox | | `switch` | — | `boolean` | Boolean toggle switch | | `select` | `options: CellSelectOption[]`, `display?` | `string` | Single-select dropdown. `display: 'text'` renders as plain text instead of badge | | `status` | `options: CellSelectOption[]`, `display?` | `string` | Color-coded status. `display: 'text'` renders as plain text instead of badge | | `enum` | `appSlug`, `dataSourceSlug`, `fieldSlug`, `options?`, `display?` | `string` | Backend-driven enum. `display: 'text'` renders as plain text instead of badge | | `user` | `options: CellUserOption[]` | `string` | User avatar + name select | | `multi-select` | `options: CellSelectOption[]` | `string` | Multi-value select with badges | | `tag-select` | `options: CellSelectOption[]` | `string` | Colored tag chips | | `date` | — | `string` | Date picker (YYYY-MM-DD) | | `datetime` | — | `string` | Date + time picker (ISO 8601) | | `time` | — | `string` | Time-only picker (HH:mm) | | `duration` | — | `string` | Duration display (HH:mm:ss) | | `date-range` | — | `string` | Date range (start,end) | | `color` | — | `string` | Color swatch + hex picker | | `icon` | — | `string` | Icon name selector | | `currency-code` | — | `string` | ISO currency code (USD, EUR, etc.) | | `file` | `maxFileSize?`, `maxFiles?`, `accept?`, `multiple?` | `FileCellData[]` | File upload cell | | `image` | `maxFileSize?`, `accept?` | `string` | Image preview + upload | | `relation` | `dataSourceId`, `displayField?` | `string` | Related record lookup (requires Docyrus) | | `rating` | `max?` | `number` | Star rating (default max: 5) | | `user-multi-select` | `options: CellUserOption[]` | `string` | Multi-user select with avatars | | `chart` | `chartType?`, `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. | Field | Type | Required | Description | |-------|------|----------|-------------| | `label` | `string` | Yes | Display label | | `value` | `string` | Yes | Internal value | | `icon` | `FC` | No | Custom icon component | | `iconStr` | `string` | No | Icon name string | | `color` | `string` | No | Badge/tag color (hex) | | `count` | `number` | No | Faceted count | ### CellUserOption Extends `CellSelectOption` with user-specific fields. | Field | Type | Required | Description | |-------|------|----------|-------------| | `...CellSelectOption` | — | — | All select option fields | | `avatarUrl` | `string` | No | User avatar image URL | | `initials` | `string` | No | Fallback initials (e.g. "AJ") | ### DataGridAction Action button definition for the bulk action bar (shown when rows are selected). | Field | Type | Required | Description | |-------|------|----------|-------------| | `label` | `string` | Yes | Action button label | | `icon` | `ReactNode` | No | Action icon | | `variant` | `'default' \| 'destructive'` | No | Button variant | | `onAction` | `(selectedRows: Array) => void` | Yes | Action callback with selected rows | ### CellChange Represents a single cell's change within a row. | Field | Type | Description | |-------|------|-------------| | `columnId` | `string` | Column ID of the changed cell | | `originalValue` | `unknown` | Value before editing | | `newValue` | `unknown` | Current edited value | ### RowChange Represents all changes in a single row. Passed to `onChangesSave` as an array. | Field | Type | Description | |-------|------|-------------| | `rowId` | `string` | Row identifier | | `rowIndex` | `number` | Row index in the data array | | `changes` | `Map` | Map of column ID → cell change | ### RowHeightValue ```tsx type RowHeightValue = 'short' | 'medium' | 'tall' | 'extra-tall'; ``` ### CellUpdate Used in paste and data update operations. | Field | Type | Description | |-------|------|-------------| | `rowIndex` | `number` | Target row index | | `columnId` | `string` | Target column ID | | `value` | `unknown` | New cell value | ### CellPosition | Field | Type | Description | |-------|------|-------------| | `rowIndex` | `number` | Row index | | `columnId` | `string` | Column ID | ### FileCellData Data shape for files in `file` and `image` cell variants. | Field | Type | Description | |-------|------|-------------| | `id` | `string` | Unique file ID | | `name` | `string` | File name | | `size` | `number` | File size in bytes | | `type` | `string` | MIME type | | `url` | `string?` | Download/preview URL | ### Direction ```tsx type Direction = 'ltr' | 'rtl'; ``` --- ## Keyboard Shortcuts | Shortcut | Action | |----------|--------| | `Arrow Keys` | Navigate between cells | | `Tab` / `Shift+Tab` | Move to next/previous cell | | `Enter` | Start editing / Confirm edit | | `Escape` | Cancel edit / Clear selection | | `Ctrl+F` | Open search | | `Ctrl+C` | Copy selected cells | | `Ctrl+X` | Cut selected cells | | `Ctrl+V` | Paste from clipboard | | `Ctrl+A` | Select all cells | | `Delete` / `Backspace` | Clear selected cells | | `Home` / `End` | Jump to first/last cell in row | | `Ctrl+Home` / `Ctrl+End` | Jump to first/last cell in grid | | `Page Up` / `Page Down` | Scroll up/down by page | | `Shift+Click` | Range selection | | `Ctrl+Click` | Toggle cell in selection |