Density

How much room a row, a control and an hour take: comfortable by default, compact chosen on any element.

The tokens

Five tokens, only the ones the dense screen proves. Comfortable is the default; compact is chosen with data-density="compact" on any element, not only :root — the custom properties inherit, so a part of a page can be compact while the rest stays comfortable. A region inside a compact one returns to comfortable with data-density="comfortable".

Comfortable is what is drawn for the row, its header and the button; the hour is 80 for the drawn 81. The drawn field is 48 at its default size and the drawn navigation item 48, where density/control and density/nav-item give 40: this page said comfortable was what is drawn (corrected 2026-09-24, fidelity audit), and which height stands is still to be decided.

Density tokens: comfortable and compact, and what reads each one
TokenComfortableCompactRead by
density/control40px32pxA control’s height when no size is passed: Button, Input, Select, NativeSelect, Combobox, DatePicker
density/row72px48pxA Table row
density/row-header44px36pxA Table header row
density/hour80px64pxAn hour in the Scheduler; a quarter of it is a card’s floor
density/nav-item40px32pxAn item in the SideNav and the SideNavSecondary

Choosing

Compact where a person scans many rows with a pointer — a dense Table, a packed Scheduler, a long SideNav — and comfortable everywhere else, which is most of a product. An explicit size on a control, and the Table’s own explicit density prop, keep winning over the token: with neither attribute, nothing changes from today.

Touch

Compact does not apply under a finger. Inside @media (pointer: coarse) the compact block restates the comfortable values, so a control stays 40px and a row 72px even with data-density="compact" set. 32px passes WCAG 2.5.8’s 24px floor, but under a thumb at 375px it reads small, and density is for the pointer and the keyboard, not the touchscreen.

Try it

The same Button, Input, Select and Scheduler slice, drawn twice: once at rest, and once inside data-density="compact". None of the controls take a size — every measurement below comes from the attribute alone.

Comfortable

Assessment
Follow-up
Sports massage
Thursday, September 17
All-day

    Compact

    Assessment
    Follow-up
    Sports massage
    Thursday, September 17
    All-day

      The client Table takes no density prop either, but it needs its own full width to prove it: below the Table’s own 258px threshold it loses its Appointment column, which is correct — and exactly what the panels above would force on it. Stacked instead, its row is 72px in the first and 48px in the second.

      Comfortable

      Ridge Physio’s clients (comfortable)
      ClientAppointment
      Maya CostaAssessment
      Joaquim OkaforFollow-up
      Aisha NguyenSports massage

      Compact

      Ridge Physio’s clients (compact)
      ClientAppointment
      Maya CostaAssessment
      Joaquim OkaforFollow-up
      Aisha NguyenSports massage

      In code

      TSX
      <div data-density="compact">
        {/* Button, Input, Select, Table and Scheduler inside read the compact values. */}
      </div>
      
      // Tailwind: the density utilities read the token where they are used.
      <div className="h-density-row">…</div>

      In Figma

      A fourth collection, Alpenglow Density, two modes, Comfortable and Compact, one variable per token above, each with scopes set to WIDTH_HEIGHT so a designer sees only the properties it applies to.