Skip to content

tech(scss): single machine-readable deprecation registry - #5132

Draft
MarcFairbrother wants to merge 8 commits into
masterfrom
tech.scss.deprecation.strategy
Draft

MarcFairbrother wants to merge 8 commits into
masterfrom
tech.scss.deprecation.strategy

Conversation

@MarcFairbrother

@MarcFairbrother MarcFairbrother commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Description

Deprecation in @lucca-front/scss was expressed four incompatible, machine-unreadable ways: silent // comments, // DEPRECATED section headers, inline value-list annotations, and config flags. None survive Sass compilation, so the VS Code IntelliSense manifest had to reconstruct deprecation from a frozen regex seed (css-api/deprecations.js) — brittle (false positives/negatives), drift-prone, and a split source of truth. It was untrustworthy enough that the extension shipped deprecation flagging off by default.

What this PR does

Introduces one authoritative, colocated, machine-readable deprecation signal that emits zero bytes into the compiled CSS.

The convention: a registry mixin

packages/scss/src/commons/deprecated.scss exposes deprecated.class(), deprecated.cssVariable(), deprecated.selector() and deprecated.sassApi(). Each records metadata into a module-level map and emits no CSS. You call it at the declaration site:

// Before — invisible to tooling, stripped at compile time
// textLeft is deprecated
.pr-u-textLeft { @extend %textLeft; }

// After — authoritative, survives to JSON, still zero CSS
@include deprecated.class('pr-u-textLeft', $replacement: 'pr-u-textAlignStart', $scope: 'commons/utils');
.pr-u-textLeft { @extend %textLeft; }

For loop-generated names (spacing/border-radius/palette utilities, the whole u- prefix) the registration lives inside the loop using the same interpolation that builds the emitted class, so the recorded name is exact by construction — no regex guessing. This is why the approach was chosen over loud /* @deprecated */ comments: comments can't anchor to @extend-merged selectors or loop output, and de-merging @extend would grow the shipped CSS.

Rule: a deprecation isn't a deprecation until it's registered.

The manifest

A build step (npm run scss:deprecations) compiles a maximal-config entry, reads the registry out through a custom Sass function, and writes packages/scss/css-api/deprecations.json (committed, deterministic, sorted). Schema:

{ "version": 1, "package": "@lucca-front/scss",
  "entries": [ { "kind": "class", "name": "pr-u-textLeft", "replacement": "pr-u-textAlignStart", "note": null, "since": null, "scope": "commons/utils" } ] }

684 entries: 477 utility classes, 140 CSS variables, 49 component selectors, 18 Sass APIs. The manifest is committed (so Storybook and typecheck work from a clean checkout) and shipped in the published package; CI runs npm run scss:deprecations -- --check to fail on drift.

Storybook page

Documentation / Integration / Deprecations — a searchable, kind-filterable table of every deprecated element and its replacement, built programmatically from the committed JSON so it updates automatically. The PR's staging build posts a live preview link.

Size audit — provably neutral

Registry calls emit no CSS. npm run scss:audit compiles the full bundle and every module before/after and compares sha256:

Output Before After Δ
bundle lucca-front.min.css 1,242,368 B 1,242,368 B 0
bundle (maximal config, u- prefix on) 1,248,519 B 1,248,519 B 0

125/125 comparable outputs are byte-identical (the full bundle + commons + 123 component modules; one pre-existing component that doesn't compile standalone is excluded). Full per-module table and the before/after deprecation inventory: scss-size-audit.md.

Commits

  1. tech(scss): add deprecation registry module and extraction tooling
  2. tech(scss): register commons deprecations through the registry
  3. tech(scss): register component deprecations through the registry
  4. tech(scss): commit generated deprecations manifest with CI drift check
  5. feat(stories): add deprecations explorer to integration documentation
  6. tech(scss): satisfy stylelint formatting and harden the audit tool
  7. docs(scss): document the deprecation registry and audit workflow

Notes & known limitations

  • Selector deprecations key on (kind, name) without scope, so a bare class shared across components (e.g. .mod-text in both button and buttonGroup) is recorded once, under one component. Compound selectors (.box.mod-grey) are unambiguous. Acceptable given the shared class name; can be refined later if needed.
  • A few --commons-* custom properties under the legacy block (container/navSide sizing) were left unregistered because they lack a clear replacement and appear semi-active internally — deliberately under-claiming rather than mis-claiming deprecation.
  • Usage-site @warn (warning consumers who include a deprecated Sass mixin) is intentionally deferred — it adds build-log noise for little value and can be a follow-up.
  • No CI size gate: size-neutrality is a property of this refactor, not a package invariant (future PRs legitimately change sizes). The audit tool is committed for one-off use.

Follow-ups (branch feat.vscode.intellisense)

  • Have css-api/generate.js consume deprecations.json and delete the regex seed css-api/deprecations.js.
  • Enable the extension's deprecation diagnostics by default now that the data is trustworthy.
  • Feed the same JSON into a stylelint rule and ng update codemods.

MarcFairbrother and others added 7 commits July 8, 2026 20:52
Introduces a single machine-readable deprecation signal for @lucca-front/scss:
a Sass registry module (commons/deprecated.scss) whose mixins register deprecated
public API (utility classes, custom properties, selectors, Sass API) at the
declaration site while emitting zero CSS, plus a build-time extractor that dumps
the registry to JSON and a size/inventory audit tool.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replaces the ad-hoc deprecation comments/annotations in commons (core.scss,
utils/index.scss, vars.scss, config.scss) with registry calls colocated at each
declaration. Covers loop-generated utility names, @extend aliases, the whole u-
prefix family, deprecated custom properties/palettes and the deprecated Sass API.
Compiled CSS is byte-identical (default and maximal config).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Migrates the per-component deprecation markers (deprecated custom properties,
legacy .mod-*/.viewTabs/.menu/.lu-dropdown-* selectors, wholly deprecated
components, and deprecated Sass mixins) to registry calls colocated with each
declaration, deleting the redundant comments. Compiled CSS is byte-identical
(default and maximal config).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds the generated css-api/deprecations.json (single machine-readable source
consumed by Storybook, CI and downstream tooling), ships it in the published
package, and fails CI if it drifts from the SCSS sources.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A searchable, kind-filterable page under Documentation/Integration/Deprecations
listing every deprecated utility class, CSS variable, component selector and
Sass API with its replacement. Built programmatically from the committed
css-api/deprecations.json so it updates automatically on future deprecations.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Applies stylelint --fix spacing around the new registry @include calls, rewords
one note to avoid a postcss-scss tokenizer quirk (regenerating the manifest),
and makes audit-size.js tolerate modules that do not compile standalone plus a
--base override to isolate a specific change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@MarcFairbrother MarcFairbrother added the 🔨 Technical Doesn't affect the output (refactor, dependencies update, cleaning, etc.) label Jul 8, 2026
@c-3po c-3po Bot added the 📖 Documentation changes Requires a Prisme update label Jul 8, 2026
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

🚀 Storybook preview deployed: https://pub-dc6d99acd6874e2aaff6219dd8a13ae2.r2.dev/PR-5132/index.html

Records the before/after compiled+compressed sizes (full bundle and every
module, all byte-identical) and the before/after deprecated-element inventory
for the registry migration.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📖 Documentation changes Requires a Prisme update 🔨 Technical Doesn't affect the output (refactor, dependencies update, cleaning, etc.)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant