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
- A tier-1 control-size ramp that
--sidenav-item-height, --back-to-top-size, --header-nav-avatar-size and friends read from.
- 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
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:
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:
Type maps. Icon size has a ramp too (
--icon-size-xs/sm/md/lg/xl= 14/16/20/24/28px) — but--sidenav-icon-size: 18pxsits off it, betweensmandmd. 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 substituteSome 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
--sidenav-item-height,--back-to-top-size,--header-nav-avatar-sizeand friends read from.--sidenav-icon-sizeonto the existing--icon-size-*ramp (18px →smormd), 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:
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: 32pxand--sidenav-icon-size: 16pxin 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