Skip to content

feat(tokens): add --sf-density control-geometry dial - #615

Merged
jackgranatowski merged 2 commits into
mainfrom
claude/slashed-bloat-reduction-bna967
Jul 15, 2026
Merged

feat(tokens): add --sf-density control-geometry dial#615
jackgranatowski merged 2 commits into
mainfrom
claude/slashed-bloat-reduction-bna967

Conversation

@jackgranatowski

@jackgranatowski jackgranatowski commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds --sf-density (PUBLIC-ADVANCED, default 1) — the compact ↔ comfortable dial for interactive control geometry. It scales the --sf-size-* rung ladder (24·32·40·48·56px at 1): below 1 packs controls tighter (dashboards, data tables, power-user tools), above 1 loosens them.

Motivation: the size ladder was previously static rem literals scaled by no knob at all — intentionally non-fluid, because control height must not shrink on small screens where touch targets need to grow (unlike --sf-text-*/--sf-space-*, which are viewport-fluid by design). That left a real gap: a project wanting denser UI had to hand-override every --sf-size-* rung plus related paddings and hope they stayed in sync. --sf-density gives that whole geometric axis one deliberate dial while preserving the non-fluid contract — it's a product/user-preference choice, never an automatic viewport response.

--sf-density is orthogonal to --sf-space-scale (overall whitespace) and --sf-section-scale (section rhythm); combine them for a fully compact UI. The --sf-touch-target accessibility floor stays independent, so a small value can't pull native controls under the WCAG target. Like the other global multipliers, it's a :root dial — the size ladder is computed at :root and inherits, so a nested override does not retroactively rescale it (same computed-value rule as --sf-space-scale et al.; documented explicitly to avoid a false claim about subtree scoping).

Changes

Tokens

  • Added: --sf-density (knob, 1) — global multiplier for the --sf-size-* ladder

CSS

  • core/tokens.css: new --sf-density token; --sf-size-xs…xl re-pointed through calc(<literal> * var(--sf-density))

Tooling / wiring

  • scripts/token-tiers.js: --sf-density classified PUBLIC-ADVANCED (alongside the other global multipliers)
  • docs/token-annotations.json: annotation added
  • docs/llm-guide.md: added to the §10 Global Scale Multipliers table with usage notes
  • configurator/src/data/domain-patterns.json: density pattern added to the spacing domain (keeps the curation test passing)
  • demos/generate.mjs: curated override value for the "ultimate override" demo
  • Generated artifacts regenerated: docs/api-index.*, docs/token-index.*, docs/tokens.md, docs/classes.md, docs/registry.json, token-registry.json, configurator/src/data/*.generated.json, dist/css-custom-data.json, static coverage artifacts (docs/test-coverage-6-token-reference.html, reports/full-api-audit/results/tokens-report.json)

Tests

  • tests/tokens.spec.js: new test verifying --sf-density uniformly scales the --sf-size-* ladder (0.8× and 1.25×) against the default 24/32/40/48/56px rungs

Bug fix (found while implementing this)

  • core/tokens.css: a comment near the new token contained --sf-text-*/--sf-space-* — the */ prematurely closed the CSS comment, which would have broken tests/tier1-p2-coverage.test.js (the same class of bug fixed in core/motion.css in the prior .sf-stagger PR). Reworded to avoid the sequence; audited the entire core/, optional/, demos/, configurator/src CSS tree for the same pattern (character-level parser + two complementary greps) — no other occurrences found.

Type

  • feat

Checklist

  • Conventional Commit messages
  • npm run lint:css passes
  • npm run build rebuilds dist/
  • npm run test:unit passes (111/111); Playwright e2e verified manually against the installed browser in this environment (full multi-browser e2e runs on CI)
  • npm run check:version passes (no version bump needed)
  • npm run check:llm-guide passes (LLM guide reviewed and updated)
  • Generated artifacts regenerated (npm run docs, npm run gen:registry, npm run audit), not hand-edited
  • CHANGELOG.md updated under ## [Unreleased]
  • No breaking changes — --sf-density is additive; the --sf-size-* ladder's default resolved values are unchanged at --sf-density: 1

Notes

Manually verified in a real Chromium instance: --sf-size-m resolves to 40px at --sf-density: 1, 32px at 0.8, 50px at 1.25; .sf-btn's default min-height tracks the ladder. Also verified that --sf-density set on a nested element does not rescale an already-computed inherited size token — confirming it must be documented as a :root-only dial, consistent with the framework's other scale multipliers.

https://claude.ai/code/session_01TsAowhRHNTVVfxvafVtDas


Generated by Claude Code

Summary by CodeRabbit

  • New Features

    • Added the advanced --sf-density control to switch interactive sizing between compact and comfortable modes.
    • --sf-density scales the --sf-size-* rung ladder while keeping the touch-target accessibility floor independent.
    • Updated the configurator and demo token reference to include --sf-density.
  • Documentation

    • Refreshed token reference materials (counts/tables) and updated guides/changelog entries for the new density control.
  • Tests

    • Added regression coverage validating default ladder values and --sf-density-driven scaling behavior.

…ywhere

--sf-density (PUBLIC-ADVANCED, default 1) is the compact <-> comfortable dial
for interactive control geometry. It scales the --sf-size-* rung ladder
(24/32/40/48/56px at 1); below 1 packs controls tighter (dashboards, data
tables, power-user tools), above 1 loosens them.

The size ladder was previously static rem literals scaled by no knob at all —
intentionally non-fluid because control height must not shrink on small screens
where touch targets need to grow. Density keeps that non-fluid contract but
gives the ladder one deliberate dial. Orthogonal to --sf-space-scale
(whitespace) and --sf-section-scale (section rhythm); combine for a fully
compact UI. The --sf-touch-target a11y floor stays independent, so a small
value can't pull native controls under the WCAG target. Like the other global
multipliers it is a :root dial (the ladder is computed at :root and inherits).

Wiring: core/tokens.css (token + re-pointed --sf-size-*), token-tiers.js
(PUBLIC-ADVANCED), token-annotations, llm-guide (global-multipliers section),
configurator domain-patterns (spacing), demo override generator, token
snapshot, static coverage artifacts, generated indexes; new tokens.spec test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TsAowhRHNTVVfxvafVtDas
@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 342627c6-9dee-4912-a5e4-38a09eb4e612

📥 Commits

Reviewing files that changed from the base of the PR and between 1c017d1 and 1d4f1ea.

📒 Files selected for processing (1)
  • reports/full-api-audit/results/tokens-report.json

📝 Walkthrough

Walkthrough

Adds the public-advanced --sf-density token, scales the --sf-size-* ladder through it, updates token metadata and demos, documents its behavior, and adds regression coverage for density-dependent computed sizes.

Changes

Density token integration

Layer / File(s) Summary
Runtime density scaling
core/tokens.css, configurator/src/data/domain-patterns.json, scripts/token-tiers.js
Defines --sf-density, applies it to the size ladder, recognizes it in the spacing domain, and classifies it as PUBLIC-ADVANCED.
Token registries and indexes
docs/api-index.*, docs/token-index.*, docs/registry.json, token-registry.json, tests/token-api.snapshot.json, reports/full-api-audit/results/tokens-report.json
Adds the token to registries and generated indexes, updates counts, and changes size-rung metadata to density-scaled consumption values.
Demo token propagation
demos/*, docs/test-coverage-6-token-reference.html
Adds density to demo references and curated overrides, and removes direct size-rung overrides from the ultimate stylesheet.
Documentation and regression coverage
CHANGELOG.md, docs/llm-guide.md, docs/token-annotations.json, docs/tokens.md, tests/tokens.spec.js
Documents density behavior and verifies default, compact, and comfortable size-ladder computations.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Configurator
  participant RootTokens
  participant SizeLadder
  participant Playwright
  Configurator->>RootTokens: Recognize and set --sf-density
  RootTokens->>SizeLadder: Scale --sf-size-* values
  Playwright->>SizeLadder: Measure computed rung sizes
  SizeLadder-->>Playwright: Return density-scaled pixels
Loading

Possibly related PRs

Suggested labels: codex

Suggested reviewers: claude

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately highlights the main change: adding the new --sf-density token as a control-geometry dial.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/slashed-bloat-reduction-bna967

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot added the codex label Jul 14, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/tokens.spec.js (1)

349-380: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Avoid shadowing the top-level measure helper.

This local measure function shadows the top-level measure helper defined at line 71. Consider renaming it to something like measureSizes to prevent confusion and improve readability.

♻️ Proposed refactor
-  const measure = () => page.evaluate(() => {
+  const measureSizes = () => page.evaluate(() => {
     const rungs = ['xs', 's', 'm', 'l', 'xl'];
     const read = () => Object.fromEntries(rungs.map((r) => {
       const el = document.createElement('div');
       el.style.blockSize = `var(--sf-size-${r})`;
       document.body.appendChild(el);
       const px = parseFloat(getComputedStyle(el).blockSize);
       el.remove();
       return [r, px];
     }));
     return read();
   });
 
-  const base = await measure();
+  const base = await measureSizes();
   // Default ladder: 24 · 32 · 40 · 48 · 56 px.
   expect(base.xs).toBeCloseTo(24, 0);
   expect(base.m).toBeCloseTo(40, 0);
   expect(base.xl).toBeCloseTo(56, 0);
 
   // Compact: every rung shrinks by the same factor — ladder preserved, not flattened.
   await page.evaluate(() => document.documentElement.style.setProperty('--sf-density', '0.8'));
-  const compact = await measure();
+  const compact = await measureSizes();
   for (const r of ['xs', 's', 'm', 'l', 'xl']) {
     expect(compact[r] / base[r], `${r} ×density`).toBeCloseTo(0.8, 2);
   }
 
   // Roomy: same knob loosens the ladder.
   await page.evaluate(() => document.documentElement.style.setProperty('--sf-density', '1.25'));
-  const roomy = await measure();
+  const roomy = await measureSizes();
   expect(roomy.m / base.m).toBeCloseTo(1.25, 2);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/tokens.spec.js` around lines 349 - 380, Rename the local measure helper
in the density ladder test to a distinct name such as measureSizes, and update
its base, compact, and roomy invocations accordingly; leave the top-level
measure helper unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@reports/full-api-audit/results/tokens-report.json`:
- Around line 3-4: Regenerate the tokens report using the existing
audit-generation script so all --sf-size-* entries reflect the current source of
truth, including the consumption role and density-scaled calc() values, not the
stale knob/rem values.

---

Nitpick comments:
In `@tests/tokens.spec.js`:
- Around line 349-380: Rename the local measure helper in the density ladder
test to a distinct name such as measureSizes, and update its base, compact, and
roomy invocations accordingly; leave the top-level measure helper unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: bc3e9d32-0a53-4a13-a65d-1b9e0c336162

📥 Commits

Reviewing files that changed from the base of the PR and between b3baa7b and 1c017d1.

⛔ Files ignored due to path filters (3)
  • configurator/src/data/api-index.generated.json is excluded by !**/*.generated.*
  • configurator/src/data/token-registry.generated.json is excluded by !**/*.generated.*
  • dist/css-custom-data.json is excluded by !**/dist/**
📒 Files selected for processing (21)
  • CHANGELOG.md
  • configurator/src/data/domain-patterns.json
  • core/tokens.css
  • demos/full-api-demo-with-overrides.html
  • demos/full-api-demo.html
  • demos/generate.mjs
  • demos/ultimate-override.css
  • docs/api-index.json
  • docs/api-index.md
  • docs/llm-guide.md
  • docs/registry.json
  • docs/test-coverage-6-token-reference.html
  • docs/token-annotations.json
  • docs/token-index.json
  • docs/token-index.md
  • docs/tokens.md
  • reports/full-api-audit/results/tokens-report.json
  • scripts/token-tiers.js
  • tests/token-api.snapshot.json
  • tests/tokens.spec.js
  • token-registry.json

Comment thread reports/full-api-audit/results/tokens-report.json
@greptile-apps

greptile-apps Bot commented Jul 14, 2026

Copy link
Copy Markdown

Greptile Summary

Adds --sf-density (PUBLIC-ADVANCED, default 1) as a single dial that uniformly scales the --sf-size-xs…xl rung ladder by rewiring each rung through calc(<literal> * var(--sf-density)). The change is correctly additive — at density 1 all resolved values are unchanged — and is fully wired through the configurator, LLM guide, registry, and demo toolchain.

  • core/tokens.css: --sf-density: 1 declared; five --sf-size-* rungs converted from static rem literals to calc(literal * var(--sf-density)). The CSS is correct; the accompanying block comment (and identical prose in docs/llm-guide.md and docs/token-annotations.json) incorrectly states that a nested --sf-density override "does not retroactively rescale" the ladder — CSS custom property var() substitution is lazy per-element, so a component-level override does in fact rescale that subtree.
  • demos/ultimate-override.css: removes five direct --sf-size-* overrides (now derived), adds --sf-density: 1.6; coverage count updated to 238/266, which correctly reflects the net reclassification.
  • tests/tokens.spec.js: new Playwright test verifies 0.8× and 1.25× uniform scaling of all five rungs at the :root scope.

Confidence Score: 4/5

The CSS change is backwards-compatible and the default ladder resolves identically; the functional implementation is solid, but three documentation artifacts make an incorrect claim about how nested overrides work.

The token wiring, tier classification, registry updates, demo changes, and test are all correct. The only substantive issue is that the block comment in core/tokens.css, the paragraph in docs/llm-guide.md, and the annotation in docs/token-annotations.json all assert that setting --sf-density on a nested element does not rescale the --sf-size-* tokens for that subtree — but CSS var() substitution is lazy, so it does. This misinformation would lead developers away from a genuinely useful component-level density pattern and could cause confusion when the real browser behaviour contradicts the docs.

core/tokens.css (block comment lines 1192-1195), docs/llm-guide.md (lines 1219-1220), and docs/token-annotations.json (--sf-density annotation) — all carry the same incorrect nested-override claim and should be updated together.

Important Files Changed

Filename Overview
core/tokens.css Adds --sf-density token and rewires --sf-size-* rungs through calc(literal * var(--sf-density)); the CSS change itself is correct (default resolves identically at density 1), but the block comment incorrectly claims nested overrides cannot rescale the ladder
docs/llm-guide.md Adds --sf-density to the §10 global multipliers table; the supplementary paragraph repeats the incorrect nested-override claim
docs/token-annotations.json Adds annotation for --sf-density; contains the same incorrect claim about nested overrides not rescaling the ladder
tests/tokens.spec.js New Playwright test verifies 0.8× and 1.25× scaling of the full size ladder at :root scope; no nested-override scenario is tested
scripts/token-tiers.js Correctly places --sf-density in the ADVANCED (PUBLIC-ADVANCED) set alongside the other global multipliers
demos/ultimate-override.css Removes direct --sf-size-* overrides (now derived), adds --sf-density: 1.6; coverage count updated from 242/270 to 238/266 which correctly reflects +1 density −5 size-rung knobs (net −4)
configurator/src/data/domain-patterns.json Adds 'density' to the spacing domain patterns so the curation test continues to pass; reasonable placement alongside space/section/gutter

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["--sf-density (default: 1)"] --> B["--sf-size-xs = calc(1.5rem × density)"]
    A --> C["--sf-size-s  = calc(2rem   × density)"]
    A --> D["--sf-size-m  = calc(2.5rem × density)"]
    A --> E["--sf-size-l  = calc(3rem   × density)"]
    A --> F["--sf-size-xl = calc(3.5rem × density)"]
    G["--sf-touch-target (accessibility.css)"] -. "independent floor" .-> H[native controls]
    B & C & D & E & F --> H
    I["--sf-space-scale"] -. orthogonal .-> A
    J["--sf-section-scale"] -. orthogonal .-> A
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A["--sf-density (default: 1)"] --> B["--sf-size-xs = calc(1.5rem × density)"]
    A --> C["--sf-size-s  = calc(2rem   × density)"]
    A --> D["--sf-size-m  = calc(2.5rem × density)"]
    A --> E["--sf-size-l  = calc(3rem   × density)"]
    A --> F["--sf-size-xl = calc(3.5rem × density)"]
    G["--sf-touch-target (accessibility.css)"] -. "independent floor" .-> H[native controls]
    B & C & D & E & F --> H
    I["--sf-space-scale"] -. orthogonal .-> A
    J["--sf-section-scale"] -. orthogonal .-> A
Loading

Reviews (1): Last reviewed commit: "feat(tokens): add --sf-density control-g..." | Re-trigger Greptile

Comment thread core/tokens.css
Comment on lines +1192 to +1195
WCAG target. Like the other global multipliers it is a :root
dial — the size ladder is computed at :root and inherits, so a
nested override does not retroactively rescale it (same
computed-value rule as --sf-space-scale et al.). */

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Nested override claim contradicts CSS specification

The comment (and matching prose in docs/llm-guide.md and docs/token-annotations.json) states that a nested --sf-density override "does not retroactively rescale" the --sf-size-* ladder. This is incorrect. CSS custom property values are token streams that are substituted lazily at used-value time in each element's own cascade context — the same mechanism used by --sf-space-scale inline in the space tokens. A descendant element with --sf-density: 0.8 set on it inherits the token stream calc(2.5rem * var(--sf-density)) for --sf-size-m; when CSS resolves var(--sf-size-m) for that element, var(--sf-density) is looked up in that element's context → 0.8, giving 2rem. The behaviour the PR says was "verified" (no rescale) only holds when reading the size from the parent element after setting density on a child — the child and its descendants do see the rescaled value. Documenting this as strictly :root-only misinforms developers who would benefit from component-level density control, which actually works by design.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked this carefully before pushing the "does not rescale" claim, and re-verified it again just now — the documented behavior is correct, and this comment describes a plausible-sounding but incorrect mental model of custom-property substitution.

The key detail: var() substitution inside a custom property's own value happens at the element where that custom property is declared (or wins the cascade), not lazily re-evaluated per consuming descendant. --sf-size-m: calc(2.5rem * var(--sf-density)) is declared once, at :root. Chromium resolves var(--sf-density) there (→ 1) and the already-substituted token stream (calc(2.5rem * 1)) is what inherits down — not the original var(--sf-density) reference. A descendant overriding --sf-density does change its own getComputedStyle(...).getPropertyValue('--sf-density'), but --sf-size-m on that descendant still reads calc(2.5rem * 1), because it was never re-declared in that scope.

Verified two ways just now:

  1. Minimal isolated case (no SLASHED CSS at all):
    :root { --k: 1; --derived: calc(10px * var(--k)); }
    .child { --k: 5; }
    <div class="child" style="width:var(--derived)"> → computed width is 10px, not 50px.
  2. Same result reproduced against the actual built dist/slashed.full.css with --sf-density on a scoped <aside>.

This isn't a novel claim either — it's the exact same phenomenon core/layout.css already documents for --sf-fluid-width (see the .sf-fluid-cq comment): "the --sf-text-* / --sf-space-* tokens are computed at :root, so their var(--sf-fluid-width) is substituted there... overriding --sf-fluid-width lower in the tree can't retroactively rewrite an already-computed inherited value." --sf-density has the identical resolution shape, so the identical caveat applies.

If someone genuinely wants scoped density, the fix mirrors .sf-fluid-cq: re-declare the --sf-size-* ladder (not just --sf-density) on the scoping element's children. That's a real, addressable feature gap, but documenting today's behavior as "already works by design" would be inaccurate and would mislead people who try <aside style="--sf-density: 0.8"> expecting it to work. Keeping the current wording.


Generated by Claude Code

The --sf-density commit added a row for the new token but left the
existing --sf-size-xs..xl rows stale (role: knob, literal rem values) —
they now derive through --sf-density (role: consumption, calc()
expressions), matching docs/token-index.json.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TsAowhRHNTVVfxvafVtDas
@jackgranatowski
jackgranatowski merged commit 26ddba5 into main Jul 15, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants