āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā š shadcn/directory/sadmann7/diceui/components/data-grid ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
```package-install
npx shadcn@2.4.0-canary.12 add "https://diceui.com/r/data-grid"
```
</Step>
<Step>
Install the [`DataGridSortMenu`](#datagridsortmenu) (optional):
```package-install
npx shadcn@2.4.0-canary.12 add "https://diceui.com/r/data-grid-sort-menu"
```
</Step>
<Step>
Install the [`DataGridRowHeightMenu`](#datagridrowheightmenu) (optional):
```package-install
npx shadcn@2.4.0-canary.12 add "https://diceui.com/r/data-grid-row-height-menu"
```
</Step>
<Step>
Install the [`DataGridViewMenu`](#datagridviewmenu) (optional):
```package-install
npx shadcn@2.4.0-canary.12 add "https://diceui.com/r/data-grid-view-menu"
```
</Step>
<Step>
Install the [`DataGridKeyboardShortcuts`](#datagridkeyboardshortcuts) (optional):
```package-install
npx shadcn@2.4.0-canary.12 add "https://diceui.com/r/data-grid-keyboard-shortcuts"
```
</Step>
</Steps>
The Data Grid component provides a comprehensive spreadsheet-like experience with:
Import the components and compose them together:
import { DataGrid } from "@/components/data-grid/data-grid";
import { DataGridSortMenu } from "@/components/data-grid/data-grid-sort-menu";
import { DataGridRowHeightMenu } from "@/components/data-grid/data-grid-row-height-menu";
import { DataGridViewMenu } from "@/components/data-grid/data-grid-view-menu";
import { DataGridKeyboardShortcuts } from "@/components/data-grid/data-grid-keyboard-shortcuts";
import { useDataGrid } from "@/hooks/use-data-grid";
const { table, ...dataGridProps } = useDataGrid({
data,
columns,
onDataChange: setData,
});
<div className="flex flex-col gap-4">
{/* Toolbar with menu components */}
<div className="flex items-center gap-2 self-end">
<DataGridSortMenu table={table} />
<DataGridRowHeightMenu table={table} />
<DataGridViewMenu table={table} />
</div>
{/* Keyboard shortcuts dialog (opens with Ctrl+/) */}
<DataGridKeyboardShortcuts enableSearch={!!dataGridProps.searchState} />
{/* Data grid */}
<DataGrid table={table} {...dataGridProps} />
</div>
The Data Grid uses a three-layer cell composition pattern:
meta.cell.variant property// Cell composition flow
<DataGridCell cell={cell} table={table} />
ā
<ShortTextCell {...props} /> // Based on variant
ā
<DataGridCellWrapper {...props}>
{/* Cell-specific content */}
</DataGridCellWrapper>
Each cell variant receives the same props and wraps its content in DataGridCellWrapper, which provides:
The Data Grid supports various cell types for different data formats:
{
id: "name",
accessorKey: "name",
header: "Name",
meta: {
label: "Name",
cell: {
variant: "short-text",
},
},
}
{
id: "notes",
accessorKey: "notes",
header: "Notes",
meta: {
label: "Notes",
cell: {
variant: "long-text",
},
},
}
{
id: "price",
accessorKey: "price",
header: "Price",
meta: {
label: "Price",
cell: {
variant: "number",
min: 0,
step: 0.01,
},
},
}
{
id: "category",
accessorKey: "category",
header: "Category",
meta: {
label: "Category",
cell: {
variant: "select",
options: [
{ label: "Electronics", value: "electronics" },
{ label: "Clothing", value: "clothing" },
{ label: "Books", value: "books" },
],
},
},
}
{
id: "skills",
accessorKey: "skills",
header: "Skills",
meta: {
label: "Skills",
cell: {
variant: "multi-select",
options: [
{ label: "JavaScript", value: "javascript" },
{ label: "TypeScript", value: "typescript" },
{ label: "React", value: "react" },
],
},
},
}
{
id: "startDate",
accessorKey: "startDate",
header: "Start Date",
meta: {
label: "Start Date",
cell: {
variant: "date",
},
},
}
{
id: "isActive",
accessorKey: "isActive",
header: "Active",
meta: {
label: "Active",
cell: {
variant: "checkbox",
},
},
}
import { DataGrid } from "@/components/data-grid/data-grid";
import { DataGridKeyboardShortcuts } from "@/components/data-grid/data-grid-keyboard-shortcuts";
import { DataGridSortMenu } from "@/components/data-grid/data-grid-sort-menu";
import { DataGridRowHeightMenu } from "@/components/data-grid/data-grid-row-height-menu";
import { DataGridViewMenu } from "@/components/data-grid/data-grid-view-menu";
import { useDataGrid } from "@/hooks/use-data-grid";
export default function MyDataGrid() {
const { table, ...dataGridProps } = useDataGrid({
data,
columns,
enableSearch: true,
});
return (
<div className="flex flex-col gap-4">
{/* Toolbar with menu components */}
<div className="flex items-center gap-2 self-end">
<DataGridSortMenu table={table} />
<DataGridRowHeightMenu table={table} />
<DataGridViewMenu table={table} />
</div>
{/* Keyboard shortcuts dialog (opens with Ctrl+/) */}
<DataGridKeyboardShortcuts enableSearch={!!dataGridProps.searchState} />
{/* Data grid */}
<DataGrid table={table} {...dataGridProps} />
</div>
);
}
Add a selection column to enable row selection:
import { Checkbox } from "@/components/ui/checkbox";
const columns = [
{
id: "select",
header: ({ table }) => (
<Checkbox
checked={
table.getIsAllPageRowsSelected() ||
(table.getIsSomePageRowsSelected() && "indeterminate")
}
onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
/>
),
cell: ({ row }) => (
<Checkbox
checked={row.getIsSelected()}
onCheckedChange={(value) => row.toggleSelected(!!value)}
/>
),
size: 40,
enableSorting: false,
enableHiding: false,
},
// ... other columns
];
Add and delete rows with callbacks:
const onRowAdd = React.useCallback(() => {
const newRow = {
id: `${Date.now()}`,
// ... other default values
};
setData(prev => [...prev, newRow]);
return {
rowIndex: data.length,
columnId: "name", // Focus this column after adding
};
}, [data.length]);
const onRowsDelete = React.useCallback((rows) => {
setData(prev => prev.filter(row => !rows.includes(row)));
}, []);
const { table, ...dataGridProps } = useDataGrid({
data,
columns,
onRowAdd,
onRowsDelete,
});
Right-click on cells to access context menu options:
onRowsDelete is provided)Hook for initializing the data grid with state management and editing capabilities.
<AutoTypeTable path="./types/docs/data-grid.ts" name="UseDataGridProps" />
Main data grid with virtualization and editing capabilities.
<AutoTypeTable path="./types/docs/data-grid.ts" name="DataGridProps" />
Column header with sorting controls and visual indicators for sort direction.
<AutoTypeTable path="./types/docs/data-grid.ts" name="DataGridColumnHeaderProps" />
Routes to the appropriate cell variant based on the column's meta.cell.variant property.
<AutoTypeTable path="./types/docs/data-grid.ts" name="DataGridCellProps" />
Base wrapper providing common functionality for all cell variants including focus management, selection state, search highlighting, and keyboard interactions.
<AutoTypeTable path="./types/docs/data-grid.ts" name="DataGridCellWrapperProps" />
Individual cell variants for different data types. Each variant implements the DataGridCellVariantProps interface and wraps its content in DataGridCellWrapper.
<AutoTypeTable path="./types/docs/data-grid.ts" name="DataGridCellVariantProps" />
Available cell variants:
You can create custom cell variants by implementing the DataGridCellVariantProps interface and wrapping your content in DataGridCellWrapper:
import { DataGridCellWrapper } from "@/components/data-grid/data-grid-cell-wrapper";
import type { DataGridCellVariantProps } from "@/types/docs/data-grid";
export function CustomCell<TData>({
cell,
table,
rowIndex,
columnId,
isFocused,
isEditing,
isSelected,
}: DataGridCellVariantProps<TData>) {
const value = cell.getValue() as YourType;
return (
<DataGridCellWrapper
cell={cell}
table={table}
rowIndex={rowIndex}
columnId={columnId}
isEditing={isEditing}
isFocused={isFocused}
isSelected={isSelected}
>
{/* Your custom cell content */}
</DataGridCellWrapper>
);
}
Individual row with virtualization for large datasets.
<AutoTypeTable path="./types/docs/data-grid.ts" name="DataGridRowProps" />
Search dialog with keyboard shortcuts for finding and navigating between matching cells in the grid.
<AutoTypeTable path="./types/docs/data-grid.ts" name="DataGridSearchProps" />
Right-click context menu for quick access to common cell and row actions like copy, clear, and delete.
<AutoTypeTable path="./types/docs/data-grid.ts" name="DataGridContextMenuProps" />
Menu for managing multi-column sorting with drag-and-drop reordering and ascending/descending controls.
<AutoTypeTable path="./types/docs/data-grid.ts" name="DataGridSortMenuProps" />
Menu for adjusting row heights between short, medium, tall, and extra-tall options with persistent preferences.
<AutoTypeTable path="./types/docs/data-grid.ts" name="DataGridRowHeightMenuProps" />
Menu for controlling column visibility with search and toggle all functionality.
<AutoTypeTable path="./types/docs/data-grid.ts" name="DataGridViewMenuProps" />
Searchable reference dialog for all available keyboard shortcuts for navigating and interacting with the data grid.
<AutoTypeTable path="./types/docs/data-grid.ts" name="DataGridKeyboardShortcutsProps" />
The Data Grid follows WAI-ARIA guidelines for grid widgets:
<KeyboardShortcutsTable shortcuts={[ { keys: ["ā", "ā", "ā", "ā"], description: "Navigate between cells", }, { keys: ["Tab"], description: "Move to next cell", }, { keys: ["Shift", "Tab"], description: "Move to previous cell", }, { keys: ["Home"], description: "Move to first column", }, { keys: ["End"], description: "Move to last column", }, { keys: ["Ctrl + Home", "Cmd + Home"], description: "Move to first cell", }, { keys: ["Ctrl + End", "Cmd + End"], description: "Move to last cell", }, { keys: ["PgUp"], description: "Move up one page", }, { keys: ["PgDn"], description: "Move down one page", }, { keys: ["Shift + ā", "Shift + ā", "Shift + ā", "Shift + ā"], description: "Extend selection", }, { keys: ["Ctrl + A", "Cmd + A"], description: "Select all cells", }, { keys: ["Ctrl + Click", "Cmd + Click"], description: "Toggle cell selection", }, { keys: ["Shift + Click"], description: "Select range", }, { keys: ["Escape"], description: "Clear selection or exit edit mode", }, { keys: ["Enter"], description: "Start editing cell", }, { keys: ["Double Click"], description: "Start editing cell", }, { keys: ["Delete"], description: "Clear selected cells", }, { keys: ["Backspace"], description: "Clear selected cells", }, { keys: ["Ctrl + F", "Cmd + F"], description: "Open search", }, { keys: ["Ctrl + Shift + S", "Cmd + Shift + S"], description: "Toggle the sort menu", }, { keys: ["Ctrl + /", "Cmd + /"], description: "Show keyboard shortcuts", }, ]} />
ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā