Koder Design — Density modes

mandatory

Three canonical page-level density modes (compact / default / comfortable) with token deltas, accessibility floor, persistence pattern, and multi-tenant override rules. Density scales Verge spacing + typography tokens uniformly through CSS custom property cascade, so consumers opt in through a single attribute on the document root.

Koder Design — Density modes

Density is the global rhythm a Koder surface ships with. Three canonical modes are supported: *ompact* *efault* *omfortable* The mode sets data-density on <html>; Verge tokens cascade through CSS custom properties so every component picks up the new rhythm without per-call overrides. Power-user tools default to *ompact* touch tablets opt in to *omfortable* public landings stay on *efault*

This is parity work with Fluent 2 (Microsoft Design), Material 3 ("Density" in the Spacing track), and Carbon ("Spacing scale + tokens"). The ratio −20% / 0% / +20% matches Fluent 2's spacing track to make a crossdesignsystem port mechanical.

R1 — When to use which mode

  • *ompact*(default for Koder admin/datadense surfaces): Outlookclass

    inboxes, Excel-class grids, log viewers, dev tools, file managers, Flow's repo browser. Power users on desktop with a mouse.

  • *efault*(default everywhere else): landing pages, marketing, docs

    (KDS site), product home, settings, dialogs, onboarding. Reading comfort + density balance.

  • *omfortable* touch tablets, kiosks, TV (10-foot UI), accessibility

    user preference. Larger hit targets, more breathing room.

The page *icks one mode*as default; user override goes into the Settings drawer (see R4). Per-component override is *ut of scope*of this spec — see § Não-escopo.

R2 — Token deltas

Density multiplies Verge tokens through a single multiplier custom property --kds-density-scale. Compact = 0.8, default = 1, comfortable = 1.2. Tokens that read through the scale automatically respect the mode:

Token family Compact Default Comfortable
--kds-space-* × 0.8 × 1 × 1.2
--kds-line-height-tight × 0.95 × 1 × 1.05
Form control min-height 32 px 40 px 48 px
Button padding (Y) 6 px 8 px 10 px
List row padding 4 px 8 px 12 px

Typography sizes from specs/fonts/typography.kmd stay constant — only spacing and component minimum dimensions scale. Rationale: changing type sizes per density mode breaks visual hierarchy and AAA contrast spot-checks done at the canonical scale.

R3 — Accessibility floor

The *omfortable*mode is the WCAG 2.2 baseline for touch targets: formcontrol minimumheight never drops below 44 px (per specs/koder-app/behaviors.kmd § Tap targets). Compact is desktop-only and intentionally violates the touch target floor; surfaces that ship compact MUST also ship a "tap target ≥ 44 px" branch behind @media (pointer: coarse) so a touch device viewing a compact surface gets the comfortable rhythm anyway.

@media (pointer: coarse) {
  [data-density="compact"] { --kds-density-scale: 1.2; }
}

This is mandatory; failure to ship it fails T3 below.

R4 — Persistence

User override persists in localStorage["koder.density"] with values compact | default | comfortable. The anti-flash script in the page shell reads the key and writes data-density on <html> before first paint — same pattern as koder.theme from specs/themes/light-dark.kmd § Persistence.

Settings drawer surfaces a 3-segment control (Compact / Default / Comfortable) below the Theme group, sharing the same visual treatment (button[role="radio"] set, aria-pressed). The drawer writes the new value to localStorage and data-density on <html> immediately.

A page MAY ship a per-page initial density via the density query parameter (?density=compact) — useful for marketing previews that demonstrate the surface at a specific rhythm. Query overrides persist *nly for the session*(sessionStorage); the persisted localStorage choice is not mutated.

R5 — Multi-tenant override

Tenants on the Koder platform MAY pin density per workspace via the workspace.density_default setting. When set, the platform shell injects the override before the anti-flash script so the user's localStorage choice still wins (R4 takes precedence). Tenants MUST NOT lock the override; a tenant that genuinely needs a fixed density (public kiosk) ships its own surface, not a tenant-platform setting.

Tests

ID Test
T1 Setting data-density="compact" on <html> reduces resolved --kds-space-md by 20% from default.
T2 Setting data-density="comfortable" increases it by 20%.
T3 @media (pointer: coarse) block forces comfortable rhythm regardless of data-density attribute.
T4 localStorage koder.density set to compact survives reload (anti-flash applies before paint).
T5 Settings drawer 3segment control reflects the current value via `ariapressed`.
T6 Percomponent overrides do NOT exist — grep for `[datadensity] inside .koder-*` components is 0.

Não-escopo

  • Per-component density override (compact button inside default form).

    Density is pagelevel by spec; tools that need a denser subregion ship a custom token scope.

  • Touchdetect autodensity. Spec defaults to default; touch devices

    opt in to comfortable via Settings or via the @media (pointer: coarse) branch (R3). Automatic OS detection would conflict with the three-way persisted user choice.

References

  • specs/themes/light-dark.kmd § Persistence — anti-flash pattern
  • specs/themes/verge.kmd § R4 — token map this scales
  • specs/fonts/typography.kmd — type scale stays constant
  • specs/koder-app/behaviors.kmd § Tap targets — touch floor
  • Fluent 2 density tracks · Material 3 spacing scale · Carbon spacing

Source: ../home/koder/dev/koder/meta/docs/stack/specs/themes/density.kmd