Skip to content

feat(api-freeze): pre-freeze API cleanup — token renames, grid renames, remove HSL fallbacks - #329

Merged
jackgranatowski merged 16 commits into
mainfrom
claude/issue-327-api-freeze-pp8lip
Jun 15, 2026
Merged

feat(api-freeze): pre-freeze API cleanup — token renames, grid renames, remove HSL fallbacks#329
jackgranatowski merged 16 commits into
mainfrom
claude/issue-327-api-freeze-pp8lip

Conversation

@jackgranatowski

@jackgranatowski jackgranatowski commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Pre-freeze public API changes. All changes are documented in docs/migration.md (0.4.x → current section).

Token renames

  • --sf-color-{family}-hover--sf-color-{family}--hover (double-dash BEM state separator)
  • --sf-color-{family}-active--sf-color-{family}--active

Applies to all 6 brand families: primary, secondary, tertiary, action, neutral, base. Lives in optional/tokens.palette.css; optional/forms.css updated to reference the new name. No back-compat alias.

Tokens removed

  • --sf-breakpoint-s / --sf-breakpoint-l — CSS custom properties cannot be used inside @container or @media query conditions (spec limitation), making these tokens non-functional as intended.
  • Entire core/tokens.color-fallbacks.css (HSL fallback system) — opt-in legacy shim for engines without light-dark() / oklch(from …). Was never included in any bundle (bundle.config.json). Removed along with 3 dedicated test files and all hasFallback / fallbackOnly tracking in the generator scripts.

New public tokens

  • --sf-border-scale — border width multiplier
  • --sf-field-radius, --sf-field-padding-block, --sf-field-padding-inline
  • --sf-button-radius, --sf-button-padding-block, --sf-button-padding-inline
  • --sf-h1-max-width--sf-h6-max-width

Dead token fix

Bind --sf-scrollbar-thumb and --sf-scrollbar-track via html { scrollbar-color } in core/base.css (tokens were declared but never consumed).

Class changes

  • .sf-grid — auto-fill primitive restored to single-word form, consistent with .sf-stack, .sf-cluster, etc. Modifiers are BEM: .sf-grid--fit, .sf-grid--xs … --2xl, .sf-grid--dense.
  • .sf-grid-1 / -2 / -3 / -4 / -6.sf-grid-cols-1 / -2 / -3 / -4 / -6 — fixed-column grids renamed to make the auto-fill vs fixed distinction explicit.
  • .sf-grid-1-2 / -2-1 / -1-3 / -3-1.sf-grid-cols-1-2 / -2-1 / -1-3 / -3-1 — ratio grids follow the same rename.
  • .sf-equal unchanged — stays as .sf-equal with --sf-equal-cols / --sf-equal-gap tokens.

New classes

  • .sf-h1.sf-h6 in optional/utilities.css — heading size utilities consuming the same --sf-h{N}-* tokens as native heading elements.

Browser support gate fixes

  • Gate light-dark() block on both light-dark() AND oklch(from …): prevents Safari 15.4–16.3 from parsing relative-color tokens with unknown syntax.
  • Split oklch(from …) block: sign()-dependent tokens (text-on-color, sf-surface auto-contrast) moved to a combined gate requiring sign(), fixing Chrome 119–137 IACVT that caused invisible text on surfaces.

Docs & tests

  • docs/migration.md, docs/architecture.md, docs/layout.md updated.
  • All hand-maintained test-coverage HTML files, token-annotations.json, and tests/token-api.snapshot.json updated.
  • HSL fallback tests (tier1-p1, tier1-p3, tier1-p11) deleted; tier1-p2 and tier1-p10 rewritten to only test what remains.
  • All generated docs (api-index, token-index, tokens.md, classes.md, registry.json) regenerated.

https://claude.ai/code/session_015fojLoqhLBDfkqFTJuSdL9

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jackgranatowski, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 55 minutes and 20 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e35f8596-835d-450b-91d1-e6aec3a1abf9

📥 Commits

Reviewing files that changed from the base of the PR and between 8058ea3 and f96cf7c.

⛔ Files ignored due to path filters (2)
  • dist/badge-essential.json is excluded by !**/dist/**
  • dist/badge-optimal.json is excluded by !**/dist/**
📒 Files selected for processing (43)
  • README.md
  • configurator/src/components/Preview.svelte
  • configurator/src/data/api-index.generated.json
  • core/accessibility.css
  • core/base.css
  • core/layout.css
  • core/macros.css
  • core/tokens.color-fallbacks.css
  • core/tokens.css
  • docs/api-index.json
  • docs/api-index.md
  • docs/architecture.md
  • docs/classes.md
  • docs/demo.html
  • docs/layout.md
  • docs/migration.md
  • docs/registry.json
  • docs/test-coverage-1-colors.html
  • docs/test-coverage-3-layout.html
  • docs/test-coverage-6-token-reference.html
  • docs/token-annotations.json
  • docs/token-index.json
  • docs/token-index.md
  • docs/tokens.md
  • optional/forms.css
  • optional/legacy.css
  • optional/tokens.components.css
  • optional/tokens.palette.css
  • optional/utilities.css
  • package.json
  • scripts/gen-api-index.js
  • scripts/gen-token-index.js
  • tests/api-index-sync.test.js
  • tests/container-queries.spec.js
  • tests/demo-visual.spec.js
  • tests/tier1-p1-srgb-validity.test.js
  • tests/tier1-p10-contrast.test.js
  • tests/tier1-p11-overrides.test.js
  • tests/tier1-p2-coverage.test.js
  • tests/tier1-p3-ordering.test.js
  • tests/tier1-p7-oldengine.test.js
  • tests/token-api.snapshot.json
  • tests/token-semantic.snapshot.json
📝 Walkthrough

Walkthrough

The PR executes v1.0 API freeze preparation across the SLASHED CSS framework: grid layout classes are renamed (.sf-grid.sf-grid-auto, .sf-equal.sf-fixed-cols), hover/active state alias tokens adopt double-dash modifier naming, new tokens are added (--sf-border-scale, heading max-width, breakpoints), sign() browser compat gating is applied to auto-contrast color tokens and the .sf-surface cascade, and forced-colors accessibility overrides are introduced.

Changes

v1.0 API Freeze Changes

Layer / File(s) Summary
Hover/active state alias token renames
core/tokens.css, optional/tokens.palette.css, optional/forms.css
All six brand family --sf-color-<family>-hover/-active custom properties renamed to double-dash form --sf-color-<family>--hover/--active in both definition files, with consumption in optional/forms.css updated to match.
New tokens and base style additions
core/tokens.css, core/base.css, optional/tokens.components.css, optional/utilities.css
Adds --sf-border-scale multiplier (border-width tokens now computed), --sf-h1..6-max-width heading line-length hooks, --sf-breakpoint-s/l read-only references, html { scrollbar-color } using theme vars, per-heading max-inline-size in base, new FIELD/BUTTON component tokens, and documented (commented) heading utility stubs in utilities.
sign() browser compat gating
core/tokens.css, core/macros.css
Initial @supports gate tightened to require light-dark() + oklch(from…); --sf-color-code-text and --sf-color-text--on-* relocated into a new dedicated gate that additionally requires sign(); .sf-surface contextual auto-contrast cascade in core/macros.css also gated on sign().
Grid/layout class renames
core/layout.css, core/macros.css, optional/overrides-example.css, docs/demo.html, docs/test-coverage-*.html, tests/*.spec.js
.sf-grid* renamed to .sf-grid-auto* and .sf-equal renamed to .sf-fixed-cols in the CSS definitions, propagated across all demo HTML files, test-coverage pages, and Playwright spec files (selectors and assertions updated).
Forced-colors accessibility overrides
core/accessibility.css
Three new rule blocks inside @media (forced-colors: active): ButtonBorder restoration for interactive controls, CanvasText fallback replacing transparent gradient text on .sf-text-gradient, and Highlight border segment on the .is-loading spinner pseudo-element.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related issues

  • api freeze #327 — This PR directly implements all the Pre-Freeze items from that issue: .sf-grid.sf-grid-auto and .sf-equal.sf-fixed-cols renames, double-dash state modifier token standardization, --sf-border-scale introduction, breakpoint reference tokens, sign() browser compat gating, and forced-colors accessibility fixes.

Possibly related PRs

  • codeslash-dev/SLASHED#20: Introduced --sf-scrollbar-thumb/--sf-scrollbar-track tokens in core/tokens.css that this PR now consumes in core/base.css for html { scrollbar-color }.
  • codeslash-dev/SLASHED#93: Added .sf-surface auto-contrast and .sf-text-gradient utilities in core/macros.css; this PR modifies the @supports gate for that same .sf-surface cascade and adds forced-colors overrides for .sf-text-gradient.
  • codeslash-dev/SLASHED#113: Directly overlaps at the token level — both PRs modify hover/active semantic state alias custom properties in core/tokens.css within the same variable definitions this PR renames.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the three main categories of changes: token renames (API consistency), grid class namespace fixes, and accessibility improvements.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/issue-327-api-freeze-pp8lip

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 and usage tips.

claude added 4 commits June 14, 2026 23:13
Token consistency:
- Rename --sf-color-{family}-hover/active → --sf-color-{family}--hover/active
  across core/tokens.css and optional/tokens.palette.css (double-dash
  convention for state/modifier separators, matching --sf-color-border--focus)
- Update optional/forms.css to reference new --sf-color-action--hover name

Browser support gates:
- Gate light-dark() block on both light-dark() AND oklch(from): prevents
  Safari 15.4–16.3 from parsing relative-color tokens with unknown syntax
- Split oklch(from) block: sign()-using tokens (text-on-color, code-text,
  sf-surface auto-contrast) moved to combined gate requiring sign() support,
  preventing Chrome 119–137 IACVT that made text invisible on surfaces

New public tokens:
- --sf-border-scale: 1 + calc(Npx * var(--sf-border-scale, 1)) for border widths
- --sf-breakpoint-s: 30em / --sf-breakpoint-l: 48em reference tokens
- --sf-field-radius/padding-block/padding-inline + --sf-button-radius/padding-block/padding-inline
- --sf-h1-max-width through --sf-h6-max-width (consumed by h1–h6 in base.css)

Dead token fix:
- Bind --sf-scrollbar-thumb and --sf-scrollbar-track via html { scrollbar-color }
  in core/base.css

Class namespace fixes:
- Rename .sf-grid → .sf-grid-auto (+ all --fit/--xs/--s/--m/--l/--xl/--2xl/--dense modifiers)
  to eliminate collision with .sf-grid-N fixed-column grids
- Rename .sf-equal → .sf-fixed-cols (+ --2/--3/--4/--6 modifiers)
  to eliminate confusion with .sf-equal-height
- Update all docs (demo.html, test-coverage-*.html) and tests accordingly

New heading utility classes:
- Add .sf-h1 through .sf-h6 in optional/utilities.css, mapping to the
  same --sf-h{N}-* tokens as the native heading elements

https://claude.ai/code/session_015fojLoqhLBDfkqFTJuSdL9
… premature utility classes

- Move --sf-field-* and --sf-button-* (radius, padding-block, padding-inline)
  from core/tokens.css to optional/tokens.components.css where component
  tokens belong; they remain part of the public API but load with the
  optional component layer, not the core
- Remove .sf-h1–.sf-h6 heading utility classes from optional/utilities.css:
  utility and component classes are scheduled for v1.0, not v0.6.0

https://claude.ai/code/session_015fojLoqhLBDfkqFTJuSdL9
Matches the pattern of optional/tokens.components.css — classes are
defined but commented out, signalling the intended v1.0 API without
shipping live code in the v0.6 cycle.

https://claude.ai/code/session_015fojLoqhLBDfkqFTJuSdL9
… borders

Three public API classes had WCAG failures in Windows High Contrast Mode:

- .sf-text-gradient: background-gradient is suppressed by forced-colors but
  color:transparent remains, making text completely invisible (IACVT).
  Reset background-image/clip and restore CanvasText color.

- .is-loading::after: spinner active segment uses --sf-color-action which
  flattens to the system background in forced-colors, producing a static
  solid circle with no perceivable motion indicator.
  Override to ButtonText / Highlight so the spinning segment is visible.

- button / input[type=submit|reset|button]: token-driven border-color:
  transparent loses the control boundary in forced-colors, rendering
  buttons as unbordered text blocks.
  Re-assert ButtonBorder to restore the visible boundary.

https://claude.ai/code/session_015fojLoqhLBDfkqFTJuSdL9

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
optional/tokens.components.css (1)

6-8: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the file header comment to reflect that FIELD/BUTTON tokens now ship.

Line 6–8 still says all declarations are commented out and the file ships 0 bytes, but Lines 48–59 are active declarations. This is now misleading during maintenance and release audits.

Suggested patch
-   This file is not yet complete. All token declarations below are
-   commented out — minified bundles ship 0 bytes from this file.
+   This file is not yet complete. Most token declarations below are
+   commented out; currently FIELD/BUTTON public tokens are active.
🤖 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 `@optional/tokens.components.css` around lines 6 - 8, Update the file header
comment in tokens.components.css (lines 6-8) to accurately reflect the current
state of the file. The existing comment states that all token declarations are
commented out and the file ships 0 bytes, but lines 48-59 contain active
FIELD/BUTTON token declarations that are now included in minified bundles.
Revise the header to note that the `@layer` declaration is in place AND that
FIELD/BUTTON token declarations are active and shipping, rather than claiming
the file still ships 0 bytes.
🤖 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.

Outside diff comments:
In `@optional/tokens.components.css`:
- Around line 6-8: Update the file header comment in tokens.components.css
(lines 6-8) to accurately reflect the current state of the file. The existing
comment states that all token declarations are commented out and the file ships
0 bytes, but lines 48-59 contain active FIELD/BUTTON token declarations that are
now included in minified bundles. Revise the header to note that the `@layer`
declaration is in place AND that FIELD/BUTTON token declarations are active and
shipping, rather than claiming the file still ships 0 bytes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 283681e0-ff31-44ff-927c-0b105325fa91

📥 Commits

Reviewing files that changed from the base of the PR and between d7820d8 and 8058ea3.

📒 Files selected for processing (17)
  • core/accessibility.css
  • core/base.css
  • core/layout.css
  • core/macros.css
  • core/tokens.css
  • docs/demo.html
  • docs/test-coverage-2-typography.html
  • docs/test-coverage-3-layout.html
  • docs/test-coverage-5-forms-features.html
  • optional/forms.css
  • optional/overrides-example.css
  • optional/tokens.components.css
  • optional/tokens.palette.css
  • optional/utilities.css
  • tests/behavior.spec.js
  • tests/demo-visual.spec.js
  • tests/layout.spec.js

- Preview.svelte: fix --sf-color-{c}-hover/active → --hover/--active,
  update .sf-grid → .sf-grid-auto and .sf-equal → .sf-fixed-cols labels
- tests/token-api.snapshot.json: update 12 hover/active token names
- docs/test-coverage-1-colors.html + demo.html: fix inline token refs
- docs/test-coverage-6-token-reference.html: update TOKENS array
- docs/token-annotations.json: rename 12 hover/active annotation keys
- docs/architecture.md: update naming-convention examples and palette
  description to reflect double-dash hover/active as application slots
- docs/layout.md: .sf-equal → .sf-fixed-cols in quick-reference table
- docs/migration.md: add hover/active and grid/equal rename entries to
  0.4.x→current section; add 0.3.x cross-reference note
- Regenerated: api-index.{json,md}, token-index.{json,md}, tokens.md,
  classes.md, registry.json, api-index.generated.json (npm run docs)

https://claude.ai/code/session_015fojLoqhLBDfkqFTJuSdL9
@jackgranatowski
jackgranatowski force-pushed the claude/issue-327-api-freeze-pp8lip branch from 8058ea3 to 8bbdf39 Compare June 14, 2026 23:22
claude added 3 commits June 14, 2026 23:38
…ignment

The class name now matches its internal tokens (--sf-equal-cols, --sf-equal-gap),
eliminating the class/token naming mismatch introduced by the intermediate
.sf-fixed-cols rename. Also fixes remaining .sf-grid → .sf-grid-auto references
missed in docs/layout.md.

https://claude.ai/code/session_015fojLoqhLBDfkqFTJuSdL9
Aligns the gap token with the class namespace (.sf-equal-cols).
Full set: .sf-equal-cols + --sf-equal-cols + --sf-equal-cols-gap.

https://claude.ai/code/session_015fojLoqhLBDfkqFTJuSdL9
…l-gap tokens

Reverts the intermediate renames (.sf-equal → .sf-fixed-cols → .sf-equal-cols
and --sf-equal-gap → --sf-equal-cols-gap). The original .sf-equal name is the
clearest and most concise; the disambiguation with .sf-equal-height does not
require a rename since both serve distinct roles.

https://claude.ai/code/session_015fojLoqhLBDfkqFTJuSdL9
@jackgranatowski jackgranatowski changed the title feat(api-freeze): implement all Category 1 pre-freeze public API changes feat(api-freeze): pre-freeze API cleanup — token renames, .sf-grid-auto, remove HSL fallbacks Jun 15, 2026
@jackgranatowski jackgranatowski changed the title feat(api-freeze): pre-freeze API cleanup — token renames, .sf-grid-auto, remove HSL fallbacks feat(api-freeze): pre-freeze API cleanup — token renames, grid renames, remove HSL fallbacks Jun 15, 2026
claude added 6 commits June 15, 2026 07:20
These read-only reference tokens document hardcoded @container values but
have no functional effect — CSS custom properties cannot be used inside
@container or @media queries per spec. They added public API surface
(SemVer obligation) without giving consumers real control.

https://claude.ai/code/session_015fojLoqhLBDfkqFTJuSdL9
…css)

The file was never included in any bundle (not in bundle.config.json),
making it an opt-in-only legacy shim for engines without light-dark() /
oklch(from …). Removing it cleans up dead surface area ahead of the
token-API freeze.

Changes:
- Delete core/tokens.color-fallbacks.css
- Remove FALLBACK_FILE logic from scripts/gen-api-index.js and
  scripts/gen-token-index.js (hasFallback, fallbackOnly, fallback_source,
  buildFallbackOnlyEntries, fallbackNames)
- Delete tests/tier1-p1-srgb-validity.test.js (tested HSL-only sRGB validity)
- Delete tests/tier1-p3-ordering.test.js (tested fallback load order)
- Delete tests/tier1-p11-overrides.test.js (tested HSL channel propagation)
- Rewrite tests/tier1-p10-contrast.test.js: keep only the fast-check pure
  math invariant (dark text on light bg >= 4.5:1); drop HSL channel reads
- Rewrite tests/tier1-p2-coverage.test.js: keep @supports-gating checks on
  tokens.css; drop fallback coverage and uniqueness assertions
- Remove deleted tests from package.json pretest command
- Remove <link> for color-fallbacks.css from README.md a la carte example
- Clean up stale fallback comment from optional/legacy.css
- Regenerate all generated docs (api-index, token-index, tokens.md, etc.)

https://claude.ai/code/session_015fojLoqhLBDfkqFTJuSdL9
… to .sf-grid-cols-N

.sf-grid (auto-fill) stays a single-word primitive consistent with
.sf-stack, .sf-cluster, .sf-sidebar etc. Modifiers restore to BEM form:
.sf-grid--fit, .sf-grid--xs … .sf-grid--2xl, .sf-grid--dense.

Fixed-column and ratio grids renamed from .sf-grid-N / .sf-grid-1-2 to
.sf-grid-cols-N / .sf-grid-cols-1-2 — making the distinction between
auto-fill (variable columns) and fixed-column (always N columns) explicit
without breaking the single-word primitive pattern.

Updated: core/layout.css, core/macros.css, optional/overrides-example.css,
all docs HTML files, layout.md, architecture.md, migration.md, all test
specs, configurator Preview.svelte, and regenerated generated docs.

https://claude.ai/code/session_015fojLoqhLBDfkqFTJuSdL9
… removal

api-index-sync.test.js:
- Remove fallback_only_tokens from counts assertion (field no longer exists)
- Remove hasFallback / fallbackOnly column checks from token row validation

tier1-p7-oldengine.test.js:
- Remove dependency on core/tokens.color-fallbacks.css
- Rewrite as @supports-gating check on the built bundle alone:
  no light-dark() / oklch(from…) / color-mix() may survive @supports stripping
- Drop sRGB-value assertions (framework no longer provides sRGB fallbacks)

https://claude.ai/code/session_015fojLoqhLBDfkqFTJuSdL9
…cale

- token-api.snapshot.json: add --sf-h1-max-width … --sf-h6-max-width
- token-semantic.snapshot.json: --sf-border-width-1 now calc(1px * 1)
  due to --sf-border-scale multiplier

https://claude.ai/code/session_015fojLoqhLBDfkqFTJuSdL9
@jackgranatowski
jackgranatowski force-pushed the claude/issue-327-api-freeze-pp8lip branch from 3a100d8 to 64eb598 Compare June 15, 2026 07:23
claude added 2 commits June 15, 2026 08:00
Three tokens added by the merged PR are now included:
- --sf-field-padding-block
- --sf-field-padding-inline
- --sf-field-radius

Sort order also corrected for --sf-color-{secondary,tertiary}--{active,hover}
which sort before -100 in ASCII order.

https://claude.ai/code/session_015fojLoqhLBDfkqFTJuSdL9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants