Skip to content

lego request: a tier-1 control-size ramp (--sidenav-item-height and friends are raw px) #29

Description

@newspaceracer

Filed from firma2-design (ProjectFirma 2.0 spoke) · 2026-08-19
Surfaced while setting the sidenav density for the spoke's first prototype.

What's missing

There is no tier-1 ramp for control/box dimensions, so every component token that needs one holds a raw px literal with nothing to point at:

--sidenav-item-height: 40px;         --sidenav-width: 280px;
--sidenav-width-collapsed: 72px;     --back-to-top-size: 44px;
--header-nav-avatar-size: 32px;      --command-palette-max-height: 440px;

Why it reads as a gap rather than a style

The hub does this correctly on every axis that has a ramp — component tokens reference it rather than restating a value:

--grid-font-size: var(--typography-label-md-font-size);
--stat-value-size: var(--font-size-700, 2.25rem);
--grid-row-font-size: var(--font-size-150);

Type maps. Icon size has a ramp too (--icon-size-xs/sm/md/lg/xl = 14/16/20/24/28px) — but --sidenav-icon-size: 18px sits off it, between sm and md. Control heights have no ramp at all.

So a spoke changing sidenav density has to write bare px, which is exactly what the token discipline otherwise forbids outside a theme's primitive ramp.

Why --spacing-* is not the substitute

Some values coincide — 40px = --spacing-650, 32px = --spacing-600, 16px = --spacing-400 — but 18px, 44px, 72px and 280px are on no step, which shows these were never derived from spacing; a few just align.

More importantly it is the wrong axis. Spacing is gap/padding. Binding row height to it means a spoke that widens its gutters silently grows its nav rows — a coupling nobody asked for.

The ask

  1. A tier-1 control-size ramp that --sidenav-item-height, --back-to-top-size, --header-nav-avatar-size and friends read from.
  2. Move --sidenav-icon-size onto the existing --icon-size-* ramp (18px → sm or md), or document why it is deliberately off-scale.

Context worth preserving

The sidenav block's own comment explains why it is currently literal — it was rewritten as a snapshot of the values the component actually ships, after a drift incident where declared defaults disagreed with painted reality:

"several were aspirational and had drifted (nested-indent said 36px while the rail rendered 16px; link-bg-hover said transparent while the row washed to surface-sunken), so declaring one thing and painting another made the surface unusable"

That fix was right. This request is the follow-on: with a ramp to point at, the shipped values can be derived rather than asserted, without reintroducing drift.

Workaround meanwhile

firma2-design re-points --sidenav-item-height: 32px and --sidenav-icon-size: 16px in its theme's [data-theme="firma2"] block — with raw px, matching the hub's own convention because there is nothing to reference.

Related

The same prototype surfaced four defects in esa-app-shell: #28

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions