jixoai-ui
the terminal design language
loading the style sheet…
Skip to content
docs · print medium: screen

design language · density kernel (2026-09-05)

2xs — the fifth rung: operation density for pro tools

Below xs sits one more rung, and only one: 2xs trades comfort for information density where the audience is a professional non-touch pointer user — inspector panels, data grids, tool palettes (IDE layers panels, Figma property panels). Every number is still an equation from the ruler: text 10px, lines 14px, rows 24px, and the sheet's ONE scoped law — the hit floor redeclares at 6U (24px, the WCAG 2.5.8 AA minimum) inside the scope, because a 2xs subtree is by construction a non-touch surface. Opt-in only, never the default: this page is the rung's standard and its acceptance demo.

5 rungs T 10px · L 14px rows 24px hit 24px = scoped 6U secondary degenerates opt-in only

the scale

Five rungs, computed live — not copied

Every bar below consumes its --jx-* alias directly inside each rung's own [data-density] scope, and the numbers are measured used values in this very page (the kernel gate's technique in real Chromium) — move the kernel and this table moves with it; it cannot rot. G stays 8px at 2xs on purpose: the xs optical floor holds one step further down (text needs its gutter, and B = G means the inset cannot shrink alone) — the compactness comes from text and block, not the inline axis.

rung T textL lineG gapS stackB insetrow-minhit-miniconimageT sec
2xs
—
—
—
—
—
—
—
—
—
—
xs
—
—
—
—
—
—
—
—
—
—
sm
—
—
—
—
—
—
—
—
—
—
default
—
—
—
—
—
—
—
—
—
—
lg
—
—
—
—
—
—
—
—
—
—
  • 2xs's hit-min (24px) is the ONE scoped floor: --jx-hit-floor redeclares at 6U inside [data-density='2xs']; every other rung and every unpinned read keep the :root 7U guardrail (28px)
  • 2xs's secondary text is honestly degenerate — max(0.625rem, 9px) = 10px = the primary size; differentiate secondary roles by ink, never by size, below xs

the scene

The same inspector at 2xs and at default

A plausible pro-tool inspector — a layers list, property rows with selects, a tool strip — built from real registry components (the Item family, Select, PressButton, Badge, Kbd). Left: the whole panel inside a 2xs scope. Right: the identical scene at default density. Nothing per-size in any component's css; one attribute moves every row.

the inspector scene — 2xs beside default

A plausible pro-tool inspector composed from real registry components: left inside a data-density='2xs' scope, right identical at default. One attribute moves every row; nothing per-size exists in any component's css. The drawer carries the sheet's REAL 2xs scope block (live extract from jixoai.css) — the scoped 24px hit floor and every alias the stage consumes.

operation surface · data-density="2xs"
layers
  • inspector/shell frame · 4 constraints
    locked ⌥1
  • inspector/rows list · virtualized
    ⌥2
  • scrim/hover overlay · pass-through
    ⌥3
  • palette/text tokens · 12 refs
    locked ⌥4
  • normal
  • multiply
  • screen
  • overlay
  • solid
  • gradient
  • none
the same scene · default
layers
  • inspector/shell frame · 4 constraints
    locked ⌥1
  • inspector/rows list · virtualized
    ⌥2
  • scrim/hover overlay · pass-through
    ⌥3
  • palette/text tokens · 12 refs
    locked ⌥4
  • normal
  • multiply
  • screen
  • overlay
  • solid
  • gradient
  • none
jixoai.css — the 2xs scope (live extract) css
/* ── the 2xs scope (2026-09-05-density-2xs) — the pro-tool extreme.
   The ONE scoped floor in the sheet (the canvas-bug law: custom
   properties substitute their var() at the DECLARING element, so a
   :root-only hit-min would hand descendants the root-substituted
   28px whatever this scope says): the scope redeclares BOTH the
   floor and the 2xs hit-min — inside it the guardrail is 6U = 24px,
   the WCAG 2.5.8 AA minimum, the deliberate pro-pointer stance for
   non-touch operation surfaces (the adoption law: opt-in only,
   never default). The §4 coefficient carrier (2026-09-21) keeps the
   scoped floor law intact: --jx-hit's frozen triple-max reads
   var(--jx-hit-floor) — resolved against THIS scope's 6U — and the
   kernel internal --jx-density-hit-min-2xs stays redeclared (the
   kernel's own, unfazed by the split). Placement keeps the chrome
   scope pinned AFTER every density scope (:where() source order). */
:where([data-density='2xs']) {
  --jx-hit-floor: calc(var(--jx-unit) * 6); /* scoped: 24px = WCAG 2.5.8 AA */
  --jx-density-hit-min-2xs: max(var(--jx-density-row-min-2xs), var(--jx-hit-floor));
  --jx-text: calc(var(--jx-density-text-2xs) * var(--jx-density-coefficient, 1));
  --jx-leading-base: var(--jx-density-leading-2xs);
  --jx-leading: calc(var(--jx-leading-base) * var(--jx-density-coefficient, 1));
  --jx-line-base: var(--jx-density-line-2xs);
  --jx-line: calc(var(--jx-line-base) * var(--jx-density-coefficient, 1));
  --jx-gap-base: var(--jx-density-inline-gap-2xs);
  --jx-gap: calc(var(--jx-gap-base) * var(--jx-density-coefficient, 1));
  --jx-media-gutter-base: var(--jx-density-media-gutter-2xs);
  --jx-media-gutter: calc(var(--jx-media-gutter-base) * var(--jx-density-coefficient, 1));
  --jx-gap-end-base: var(--jx-density-end-gap-2xs);
  --jx-gap-end: calc(var(--jx-gap-end-base) * var(--jx-density-coefficient, 1));
  --jx-stack-base: var(--jx-density-stack-gap-2xs);
  --jx-stack: calc(var(--jx-stack-base) * var(--jx-density-coefficient, 1));
  --jx-inset-base: var(--jx-density-inline-inset-2xs);
  --jx-inset: calc(var(--jx-inset-base) * var(--jx-density-coefficient, 1));
  --jx-chip-radius-base: var(--jx-density-chip-radius-2xs);
  --jx-chip-radius: calc(var(--jx-chip-radius-base) * var(--jx-density-coefficient, 1));
  --jx-gap-content-base: var(--jx-density-content-gap-2xs);
  --jx-gap-content: calc(var(--jx-gap-content-base) * var(--jx-density-coefficient, 1));
  --jx-row-min: max(
    calc(var(--jx-unit) * var(--jx-density-row-floor-2xs)),
    calc(
      (var(--jx-density-line-2xs) + var(--jx-density-stack-gap-2xs) + var(--jx-density-stack-gap-2xs)) *
      var(--jx-density-coefficient, 1)
    )
  );
  --jx-hit: max(
    var(--jx-hit-floor),
    calc(var(--jx-unit) * var(--jx-density-row-floor-2xs)),
    calc(
      (var(--jx-density-line-2xs) + var(--jx-density-stack-gap-2xs) + var(--jx-density-stack-gap-2xs)) *
      var(--jx-density-coefficient, 1)
    )
  );
  --jx-icon-base: var(--jx-density-media-icon-2xs);
  --jx-icon: calc(var(--jx-icon-base) * var(--jx-density-coefficient, 1));
  --jx-image-base: var(--jx-density-media-image-2xs);
  --jx-image: calc(var(--jx-image-base) * var(--jx-density-coefficient, 1));
  --jx-text-secondary-base: var(--jx-density-secondary-text-2xs);
  --jx-text-secondary: calc(var(--jx-text-secondary-base) * var(--jx-density-coefficient, 1));
  --jx-leading-secondary-base: var(--jx-density-secondary-leading-lg);
  --jx-leading-secondary: calc(var(--jx-leading-secondary-base) * var(--jx-density-coefficient, 1));
  --jx-line-secondary-base: var(--jx-density-secondary-line-2xs);
  --jx-line-secondary: calc(var(--jx-line-secondary-base) * var(--jx-density-coefficient, 1));
  --jx-toggle-track: var(--jx-line);
  --jx-toggle-width: calc(var(--jx-toggle-track) * 2);
  --jx-toggle-knob: calc(var(--jx-toggle-track) - var(--jx-unit));
  --jx-slider-track: max(var(--jx-unit), calc(var(--jx-line) / 2));
  --jx-textarea-min: max(var(--jx-hit), calc(var(--jx-line) * 3 + var(--jx-stack) * 2 + 2px));
  --jx-color-lane: max(var(--jx-hit), calc(var(--jx-icon) + var(--jx-inset) * 2 + 2px));
}
  • what to see at 2xs: 24px rows (down from 40), 10px body text, 14px icons, 28px images — and hit lanes that stop at 24px, the scoped floor, instead of re-inflating to the 28px guardrail
  • the two selects share one bound state with this page — the scene is live, not a screenshot; toggle them

law

The adoption law — opt-in operation surfaces only

2xs is a scoped tool, not a product-wide mood. FOR: professional non-touch high-density operation surfaces — inspector panels, property rows, data grids, tool palettes, layers lists — where information density IS the feature and the pointer is precise. NEVER: general marketing or docs UI, prose surfaces, touch-first flows, auth or checkout. NOT the default anywhere: DEFAULT_DENSITY stays 'default', no family fallback becomes 2xs, the canvas stage's density select keeps the standard four stops (xs/sm/default/lg). xs keeps its own role (dense non-touch metadata surfaces); 2xs goes further (operation surfaces) — a product can run an xs nav rail beside a 2xs inspector.

the 2xs derivation (design §1)
T_2xs      = T_base − 3·U/4          → 10px  (the pro-tool body; 9px stays UNSHIPPED)
L_2xs      = T_2xs × 14/10           → 14px  (integer line, the xs precedent)
G_2xs      = U × 2                   → 8px   B_2xs = G_2xs  (THE balance invariant —
                                                      the inset cannot shrink without
                                                      hurting every control at once)
S_2xs      = U × 1                   → 4px
contentGap = max(U/2, S/2)           → 2px
rowMin     = max(L + 2·S, 6·U)       → max(22, 24) = 24px  (the floor side wins —
                                                      pinned AT WCAG 2.5.8 AA)
hitMin     = max(rowMin, hitFloor)   → 24px INSIDE the scope — the ONE scoped floor
                                     (--jx-hit-floor: 6U inside [data-density='2xs'];
                                      the :root guardrail stays 7U everywhere else)
icon = L → 14px · image = 2L → 28px · media gutter = G = 8px
secondary  = max(0.625rem, T − U/4)  → 10px — DEGENERATE: equals the primary size,
                                       the role distinction dies at its floor
the opt-in
<!-- the whole opt-in: ONE attribute on the operation-surface root -->
<section data-density="2xs">
  <!-- layers list, property rows, tool palettes — every child scales -->
</section>

<!-- component opinion: the same single prop as any rung -->
<ItemGroup density="2xs"><!-- … --></ItemGroup>
  • the scoped floor is the sheet's ONLY scoped floor — legal because stamping data-density='2xs' declares the modality (professional non-touch pointer), the same opt-in semantics the 2026-08-29 ruling established for the 28px guardrail; 24px still satisfies WCAG 2.5.8 AA
  • 9px body exists in the grammar (one more −U/4 step) and stays UNSHIPPED — going below 10px is a new ruling, not a parameter tweak
  • verified: the kernel gate asserts the whole 2xs row in real Chromium (node scripts/verify-density-kernel.mjs), and the context specs lock resolution + stamping — see the change openspec/changes/2026-09-05-density-2xs
jixoai-ui ui.jixoai.com the jixoai design language

Theme

Brand hue

0°

Auto cycle · 24h