Density
Density is the row height: 32, 40 or 48 pixels. The user picks it from the toolbar; you can set the start, or own it from outside the grid.
| Mateo Dubois | mateo.dubois@corp.example | Active | Sales | $435.00 |
| Meera Müller | meera.muller@team.dev | Paused | Design | $0.00 |
| Amelia Smith | amelia.smith@mail.test | Active | Sales | $1,422.00 |
| Lucas Dubois | lucas.dubois@team.dev | Churned | Finance | $0.00 |
| Rohan Menon | rohan.menon@mail.test | Active | Platform | $1,566.00 |
| Saanvi Bose | saanvi.bose@mail.test | Active | Growth | $553.00 |
| Olivia Okafor | olivia.okafor@example.com | Active | Design | $0.00 |
| Noah Tanaka | noah.tanaka@example.com | Active | Platform | $24.00 |
| Rohan Patel | rohan.patel@example.com | Active | Data | $36.00 |
| Nia Dubois | nia.dubois@corp.example | Active | Design | $48.00 |
import * as React from "react";import { Rows2Icon, Rows3Icon, Rows4Icon } from "lucide-react";
import { DataGrid, createDataGridColumns, type DataGridDensity,} from "@/components/ui/data-grid";import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
import { makePeople, STATUS_OPTIONS, type Person } from "@/lib/data-grid-demo-data";
const col = createDataGridColumns<Person>();
const columns = col.columns([ col.text("name", { header: "Name" }), col.text("email", { header: "Email", size: 240 }), col.enum("status", { header: "Status", options: STATUS_OPTIONS }), col.text("team", { header: "Team" }), col.currency("mrr", { header: "MRR", currency: "USD" }),]);
const data = makePeople(40, 37);
/** Density owned by the page: this toggle and the toolbar's density menu change the same state. */export default function DataGridDensity() { const [density, setDensity] = React.useState<DataGridDensity>("compact"); return ( <div className="flex flex-col gap-3"> <ToggleGroup value={[density]} onValueChange={([next]) => { if (next) setDensity(next as DataGridDensity); }} variant="outline" size="sm" aria-label="Row density" > <ToggleGroupItem value="compact"> <Rows4Icon /> Compact </ToggleGroupItem> <ToggleGroupItem value="comfortable"> <Rows3Icon /> Comfortable </ToggleGroupItem> <ToggleGroupItem value="spacious"> <Rows2Icon /> Spacious </ToggleGroupItem> </ToggleGroup> <DataGrid key="density" data={data} columns={columns} getRowId={(row) => row.id} density={density} onDensityChange={setDensity} /> </div> );}Use it
Section titled “Use it”The toolbar’s density button (the rows icon) opens a menu with Compact, Comfortable and Spacious. Comfortable is the default.
Set a starting density, uncontrolled:
<DataGrid data={data} columns={columns} defaultDensity="compact" />Or control it, the way the demo does with a toggle outside the grid:
const [density, setDensity] = React.useState<DataGridDensity>("compact")
<DataGrid data={data} columns={columns} density={density} onDensityChange={setDensity} />Either way the menu keeps working: when you control it, it calls onDensityChange. From code,
grid.density holds the current value, grid.setDensity(next) changes it, grid.rowHeight is the
pixel height.
How it behaves
Section titled “How it behaves”-
One variable. The grid root sets
--dg-row-height(32px,40pxor48px) anddata-density="compact" | "comfortable" | "spacious". Header cells, body cells, footer cells, the pinned-row offsets, the overlay inset and the virtualizer’s size estimate all read the variable, so a density change is one style write. -
Style with it. Target the attribute for anything that should change with density, in CSS or with a Tailwind arbitrary variant on your own cells:
col.text("notes", { cellClassName: "[[data-density=compact]_&]:text-xs" })[data-slot="data-grid"][data-density="spacious"] td { font-size: 0.95rem; }Your own parts can size to a row with
h-(--dg-row-height). -
Where the start comes from. A persisted view wins; then
defaultDensity; theninitialState.density; then"comfortable". When you passdensity, the prop wins over all of them, and applying a saved view or Reset view reaches you throughonDensityChangerather than changing anything itself. -
Persistence. Density is part of the view the grid remembers with
persistand of saved views. -
Labels.
density,densityCompact,densityComfortableanddensitySpaciousinlabelsrename the menu.toolbar={{ density: false }}hides it.
Options
Section titled “Options”| Option | Type | Default | What it does |
|---|---|---|---|
density |
DataGridDensity |
Controlled density: "compact", "comfortable" or "spacious". |
|
defaultDensity |
DataGridDensity |
"comfortable" |
Uncontrolled start. |
onDensityChange |
(density) => void |
Called on every change, from the menu, setDensity or a saved view. |
|
initialState.density |
DataGridDensity |
Another way to set the start; defaultDensity wins over it. |
Exports:
| Export | What it holds |
|---|---|
DENSITY_ROW_HEIGHT |
{ compact: 32, comfortable: 40, spacious: 48 }. |
DataGridDensity |
The union type. |
DataGridDensityMenu |
The toolbar menu, for your own layouts. |
See also
Section titled “See also”- Theming and styling: the other tokens the grid reads.
- Composition and custom layouts: placing the density menu yourself.
- Saved views and persistence.