Density
Density is the cross-cutting knob that retunes padding, gaps and control heights without touching color or radius. comfortable is the marketing-first default; compact is the application-UI preset.
Two densities#
The same Card, rendered comfortable (the default) and compact. Only spacing and title scale change - corners stay the brand 16px radius.
On a real block#
Density isn’t a one-component knob. Here it drives a whole sign-in block: toggle it and the card retunes all at once - comfortable opens the padding, gaps and title up for a roomier marketing feel, compact tightens everything for dense app UI.
Welcome back
Sign in to your account to continue.
Don't have an account? Sign up
Application-UI spec#
The compact preset, modelled on a dense dashboard: 16px padding and gaps, 1rem card titles, 14px muted descriptions, and controls that aren’t too tall.
| comfortable | compact | |
|---|---|---|
| Card padding / gap | p-6 · gap-6 | p-4 · gap-4 (16px) |
| Card title | text-lg | text-base (1rem) |
| Card description | text-sm muted | text-sm muted |
| Button height (default md) | h-9 (36px) | h-9 (36px) |
| Dialog padding / gap | p-6 · gap-4 | p-4 · gap-3 |
| Tabs pill | rounded-xl p-1 | rounded-lg p-0.5 |
Set it once for a subtree#
Wrap an app shell in DensityProvider and every nested Koala component tightens up - no per-instance props. Resolution precedence is explicit prop > nearest provider > comfortable, so any component can opt back out.
import { DensityProvider } from "@/lib/density"
export function Dashboard({ children }) {
// Everything inside renders compact unless a component sets density itself.
return <DensityProvider density="compact">{children}</DensityProvider>
}Which components honor density#
Density reaches across the library: controls (Button, Select, Tabs, Pagination), surfaces (Card, Dialog, Drawer), data display (Stat, List, Description List, Data Table) and the form blocks all retune. Avatar and Badge opt out by design - they already own explicit pixel size scales, so a spacing axis would be redundant.
Reading density makes a component a client component. Card, Dialog and Tabs already were; Button is now "use client" too, so it can participate in provider-driven density.