Skip to contentVibraUI
Foundation

Density

The four variables a dashboard's rhythm is laid out on, and the compact set that tightens them.

Add the file — an @import at the end of app/globals.css, or an import in the root layout — and set data-density="compact" on <html> to tighten the page; leave the attribute off for the comfortable rhythm the :root block already declares. Four variables, one file: --density-row (table and list rows), --density-cell-y (cell padding), --density-card (card padding) and --density-gap (grid and stack gaps). The primitives that set a dashboard's rhythm read them — data-table rows and cells, stat-card and chart-card padding, stat-card-group and dashboard-grid gaps, data-list items, app-sidebar items, page-header spacing — each with the comfortable value as a literal fallback, so an item installed without this file still lays out correctly and only the switch is missing. It is a separate item from theme-vibra on purpose: a project can want the rhythm without wanting the palette, and nothing here is a colour. Write the attribute by hand, or install use-density and DensityToggle, which write it and remember the choice; AppShell takes a density prop for a page that has an opinion of its own. Deliberately not part of a preset: [data-preset] carries colour, and a palette that redefined these on a wrapper would reset the density chosen on <html> for everything inside it.

Install

npx shadcn@latest add @vibra/density

Needs the @vibra registry in your components.json — set it up once.

Examples

Props

PropTypeDefaultDescription
--density-rowlength2.75rem / 2.25rem compactThe height a data-table row and an app-sidebar item are sized from.
--density-cell-ylength0.75rem / 0.375rem compactVertical padding inside a table cell and a data-list item.
--density-cardlength1rem / 0.75rem compactA stat card's and a chart card's --card-spacing.
--density-gaplength1rem / 0.75rem compactThe gap in a stat-card group, a dashboard grid and a page header.

Source

app/vibra-density.css
/* Density — the rhythm a dashboard is laid out on, in one place so a table
   row, a card's padding and a grid's gap stay in proportion when it changes.
   Its own file, and its own registry item, because a project can want the
   density switch without wanting Vibra's palette: add the file, set
   `data-density` on <html>, and every primitive that sets a dashboard's rhythm
   follows.

   Deliberately not scoped to a preset: `[data-preset]` carries colour, and a
   palette that redefined these on a wrapper would reset the density chosen on
   <html> for everything inside it.

   The primitives read them with the comfortable value as a fallback
   (`py-[var(--density-cell-y,0.75rem)]`), so an item installed without this
   file still lays out correctly and only the switch is missing. */
:root {
  --density-row: 2.75rem;
  --density-cell-y: 0.75rem;
  --density-card: 1rem;
  --density-gap: 1rem;
}

[data-density="compact"] {
  --density-row: 2.25rem;
  --density-cell-y: 0.375rem;
  --density-card: 0.75rem;
  --density-gap: 0.75rem;
}