Visual Control Geometry Tokens (CEM) — Canonical Spec

Status: Canonical (v1.0)

Last updated: August 10, 2026

Audience: Design Systems, Product Design, Front-End Engineering

Applies to: Visual sizing of generic controls and component-affordance geometry (button, input, icon button, list/menu/table rows, progress and slider graphics)

Companion specs:


1. Why split Controls from Coupling

Visual control geometry (height, padding, icon-button size, row heights) and operability safety (zone/guard/halo) historically lived together in D2 Coupling. Splitting them clarifies responsibilities:

The two contracts are coupled by policy: visual geometry MUST NOT shrink the operable zone below --cem-coupling-zone-min, and adjacency MUST respect --cem-coupling-guard-min regardless of how Controls geometry shrinks under compact.

See cem-controls-reasoning.md for the rationale behind the split.


2. Taxonomy placement

Boundary heuristic:


3. Canonical control geometry tokens

3.1 Baseline (balanced mode)

:root {
  /* Generic control geometry */
  --cem-control-height: 2.5rem;
  --cem-control-padding-x: 0.75rem;
  --cem-control-padding-y: 0.5rem;

  /* Icon buttons: typically make the visible container meet the operable zone */
  --cem-icon-button-size: var(--cem-coupling-zone-min);
  --cem-icon-button-icon-size: 1.25rem;

  /* Standalone icons */
  --cem-icon-size: 2rem;
  --cem-icon-size-small: 1rem;
  --cem-icon-size-large: 3rem;

  /* Lists / menus */
  --cem-list-row-height: 3rem;
  --cem-list-popup-rows: 8;
  --cem-menu-row-height: 3rem;

  /* Data tables */
  --cem-table-row-height: 2.5rem;
}
cem-controls-geometry
TokenValueDescriptiontier
--cem-control-height2.5remGeneric control heightrecommended
--cem-control-height-small2.5remSmall control profile minimum visible heightrecommended
--cem-control-height-medium3remMedium control profile minimum visible heightrecommended
--cem-control-height-large4remLarge control profile minimum visible heightrecommended
--cem-control-height-x-large6remX-large control profile minimum visible heightrecommended
--cem-control-height-xx-large8remXX-large control profile minimum visible height; content may grow beyond itrecommended
--cem-control-padding-x0.75remGeneric control inline paddingrecommended
--cem-control-padding-y0.5remGeneric control block paddingrecommended
--cem-icon-button-sizevar(--cem-coupling-zone-min)Icon button visible container size; meets zone minimum by defaultrecommended
--cem-icon-button-icon-size1.25remIcon glyph size within an icon buttonrecommended
--cem-icon-size2remNormal standalone icon sizerecommended
--cem-icon-size-small1remSmall standalone icon sizerecommended
--cem-icon-size-large3remLarge standalone icon sizerecommended
--cem-list-row-height3remList row heightrecommended
--cem-list-popup-rows8Default maximum visible rows in a transient list popuprecommended
--cem-menu-row-height3remMenu row heightrecommended
--cem-table-row-height2.5remData table row heightrecommended

3.1.1 Optional size profiles

data-cem-size="small|medium|large|x-large|xx-large" selects an inherited control-height profile on any container. Components may expose size with the same values and select the corresponding public height token on their host. Omission (or an unknown value) adds no local height override. Removing an explicit size restores the container's geometry. Local custom properties can override the selected profile.

cem-controls-size-profiles
SizeHeight
smallvar(--cem-control-height-small)
mediumvar(--cem-control-height-medium)
largevar(--cem-control-height-large)
x-largevar(--cem-control-height-x-large)
xx-largevar(--cem-control-height-xx-large)

These are minimum visible heights, not fixed boxes. Width and stretch remain owned by content and CSS layout. Typography, icon sizes and padding retain their existing inherited values. Coupling modes remain independent; an explicit size profile selects height while coupling continues to govern padding and safety. On the same element, a size profile wins over a coupling height override.

Choose the profile for available space and prominence; an icon alone does not require a large control. Image/title and hero compositions may use x-large and xx-large while growing with their content. Size does not select a content layout or change an action into a navigation link. See the dimension decision.

Small/default geometry below D2's minimum reserves a transparent native-button border inside the operable bounds. Paint is clipped to the padding box; focus surrounds the complete target. The inset is half the positive difference between the operable minimum and requested visual height, otherwise zero. Layout growth can enlarge the surface without enlarging the allocated box. This is not a visible outline and does not replace zebra. Containers must leave at least the D2 guard between targets. Size profiles never change the safety minimum.

3.2 Progress graphic geometry

Circular progress is non-interactive, so its visual size is not an operable-zone claim and does not grow or shrink with coupling mode. D2c still owns the single-component geometry: the outer diameter and the visible track thickness. D0 owns track/indicator color, and D7 owns any indeterminate cycle.

cem-progress-geometry
TokenValueDescriptiontier
--cem-progress-spinner-size3remDefault circular progress diameterrequired
--cem-progress-track-thickness0.25remCircular or linear progress track thicknessrequired

3.3 Slider graphic geometry

Slider track thickness and visible thumb diameter are single-component visual geometry. D2c owns those sizes; D2 continues to own the larger operable target through --cem-coupling-zone-min, and D5 owns focus-outline geometry. A slider implementation MUST keep its native thumb hit target at least zone-min even when the visible thumb is smaller.

cem-slider-geometry
TokenValueDescriptiontier
--cem-slider-track-thickness0.25remVisible remaining and active value-range track thicknessrequired
--cem-slider-thumb-size1.25remVisible circular slider thumb diameter inside the D2 operable targetrequired

3.4 Coupling-mode overrides (visual geometry only)

Controls geometry varies by coupling mode. The mode selector is owned by D2 Coupling (data-cem-coupling="forgiving|balanced|compact"); Controls only emits the visual override values for those modes. The safety contract (zone-min, guard-min) does NOT change.

:root[data-cem-coupling="forgiving"] {
  --cem-control-height: 2.75rem;
  --cem-control-padding-x: 1rem;
  --cem-control-padding-y: 0.625rem;

  --cem-list-row-height: 3.25rem;
  --cem-menu-row-height: 3.25rem;
}

:root[data-cem-coupling="compact"] {
  --cem-control-height: 2.25rem;
  --cem-control-padding-x: 0.625rem;
  --cem-control-padding-y: 0.375rem;

  --cem-list-row-height: 2.75rem;
  --cem-menu-row-height: 2.75rem;
}
cem-controls-geometry-overrides
Tokenforgivingcompact
--cem-control-height2.75rem2.25rem
--cem-control-padding-x1rem0.625rem
--cem-control-padding-y0.625rem0.375rem
--cem-list-row-height3.25rem2.75rem
--cem-menu-row-height3.25rem2.75rem

Governance rule: visual geometry shrinks under compact only as far as the operable contract allows. When visual size drops below --cem-coupling-zone-min, components MUST use halo expansion (see D2 §6.1) so the operable zone still meets the safety contract.


4. Cross-spec consumers


5. Implementation patterns

5.1 Generic control sizing

.cem-control {
  block-size: var(--cem-control-height);
  padding-inline: var(--cem-control-padding-x);
  padding-block: var(--cem-control-padding-y);

  /* Safety: do not let visual height collapse the operable zone */
  min-block-size: var(--cem-coupling-zone-min);
}

5.2 Icon buttons

.cem-icon-button {
  inline-size: var(--cem-icon-button-size);
  block-size: var(--cem-icon-button-size);
}

.cem-icon-button > svg {
  inline-size: var(--cem-icon-button-icon-size);
  block-size: var(--cem-icon-button-icon-size);
}

If a product wants visible icon containers below --cem-coupling-zone-min, wrap them with halo expansion (see cem-coupling.md §6.1) so operability is preserved.

5.3 Rows

.cem-list-row  { min-block-size: var(--cem-list-row-height); }
.cem-list-popup { max-block-size: calc(var(--cem-list-row-height) * var(--cem-list-popup-rows)); }
.cem-menu-row  { min-block-size: var(--cem-menu-row-height); }
.cem-table-row { block-size:     var(--cem-table-row-height); }

For data tables where row visuals fall below the safety zone, ensure interactive cells (selection, action buttons) meet --cem-coupling-zone-min independently.


6. Acceptance criteria

A draft becomes "canonical" when all of the following are true:

  1. Visual-only contract: this spec emits only --cem-control-*, --cem-icon-*, list/menu/table geometry, --cem-progress-* graphics, and --cem-slider-* visual geometry tokens. Safety tokens (--cem-coupling-*) are NOT emitted here.
  2. Mode overrides only adjust visuals: forgiving/compact mode tables touch geometry, never zone/guard.
  3. Halo escape hatch documented: any time visuals fall below --cem-coupling-zone-min, halo expansion is the stated remedy.
  4. D3 Shape dependency satisfied: --cem-control-height is declared here so Shape's round-end formula resolves.

7. Token manifest index

Source tableSectionDescription
cem-controls-geometry§3.1Baseline visual control geometry: height, padding, icon-button, list/menu/table row sizes
cem-controls-size-profiles§3.1.1Size selectors referencing baseline profile tokens; no additional tokens
cem-progress-geometry§3.2Circular-progress diameter and shared progress-track thickness
cem-slider-geometry§3.3Slider track thickness and visible thumb diameter
cem-controls-geometry-overrides§3.4Forgiving/compact override values for visual geometry (generator-only; no new tokens)

Generator derivation rules: