Fix dangling --wb-* custom properties + token-usage guard - #83
Open
librowski wants to merge 21 commits into
Open
Fix dangling --wb-* custom properties + token-usage guard#83librowski wants to merge 21 commits into
librowski wants to merge 21 commits into
Conversation
librowski
requested review from
lukasz-jazwa,
piotrblaszczyk and
szymon-t-sc
as code owners
August 20, 2026 16:32
23 CSS variable names were used via var() but defined nowhere — --ax- prefix typos, misspelled token names, and two edge-label variables with no definition. Form message (neutral/warning) and the variables-settings modal were visibly rendering without their intended colors and spacing. Redundant fallbacks that masked the typos are dropped in the same lines; where a used name has no token equivalent, the value-equivalent token is substituted (tab-header 16px gap -> spacing-16).
…area icon-switch: the base thumb background referenced a variable that never existed and is always overridden by the primary/secondary variant rule — dropped the dead declaration. text-area: the disabled background variable was consumed but never defined; define it as transparent (today's effective render) so the --ax-public-* override contract actually works.
The real token is --ax-txt-secondary-default. The shorter name never existed, so the hardcoded gray fallback was what actually rendered. Remaining dead fallbacks in this file are dropped alongside.
Every one of these var(--ax-…, fallback) fallbacks is unreachable — the token is defined in the shipped tokens.css, so the fallback never wins. They also mask exactly the typo class the new token-usage lint catches, which now rejects unannotated fallbacks on system tokens.
lint-token-usage.mjs validates every var(--…) in packages/*/src and apps/*/src against the names that actually exist (tokens dist, source definitions incl. inline styles and setProperty, the provisional registry, and a runtime allowlist). Unknown names and unannotated fallbacks on system tokens are errors. Full-scan and per-file modes, self-builds dist when missing, and reports the var(--ax-*) usage count as the DS 2.0 migration meter.
CI runs the full scan in the ui job right after pnpm build:ui, so the dist it validates against is the one just built. lint-staged runs the per-file mode on staged css/ts files; the script path is anchored to the repo root because workspace lint-staged configs re-export the root config and run commands from their own directory.
The hand-rolled regex scanner (~160 lines, growing with every review finding: comments, multi-line var(), @Property, template literals) becomes configuration: csstools/value-no-unknown-custom-properties validates every var(--…) in workspace CSS against definitions collected by a small importFrom module (token dist + all source CSS + a short runtime-defined list), and a ~40-line local stylelint rule keeps the fallback ban on system tokens, with exceptions via the standard stylelint-disable-next-line comment and a mandatory reason. A real CSS parser fixes two scanner bugs for free (var() inside comments no longer flags, multi-line var() no longer escapes) and apps/docs is now excluded consistently in CI, lint-staged, and manual runs via ignoreFiles. The DS 2.0 migration meter stays as a one-liner in the CI step. Lockfile note: adding the stylelint devDependencies also re-resolves stale transitive typescript peer entries (5.9.3 -> 5.6.3) that no declared range permits — a one-time correction; declared ranges are all ~5.6.3.
--ax-colors-gray-800 is a mode-less primitive; on the dark theme it lands dark-on-dark (1.61:1) against the theme-aware secondary background. --ax-txt-primary-default resolves to the same gray-800 in light and to gray-100 in dark. The sdk changeset is reworded around the changes a consumer can actually see (the message variants are not reachable from the public API yet), and the ui changes from this PR get their missed changeset (a new public TextArea variable is an API addition).
--wb-edge-color, -temporary, -hover, and -select have zero consumers — the live edge colors are the --ax-public-edge-color-* pair in packages/ui. The label-edge variables that are consumed stay; the stale missing-token comments on them pointed at tokens that exist.
…e meter The csstools rule resolves importFrom against process.cwd(), and lint-staged runs commands from workspace directories — caught by the pre-commit hook itself. The config moves to .stylelintrc.mjs and anchors the path via import.meta.url. The DS 2.0 migration meter moves out of an inline CI shell string into tools/migration-meter.mjs behind pnpm migration:meter.
Informational, not a gate — pnpm migration:meter stays as an on-demand command for migration PRs.
…disables A central RUNTIME_DEFINED list in the definition collector rots and hides the reason away from the code. Each of the five usage sites of a JS-set variable now carries a stylelint-disable comment with the reason — self-cleaning: remove the usage and the exception goes with it.
Informational-only; lives on as a private local script for the DS 2.0 migration work instead of shipped tooling.
The designer changelog lands verbatim in packages/tokens/migration/ on the integration branch; prettier reformatting it corrupted token paths inside emphasis markers. Prettier reads .prettierignore only from the cwd and lint-staged runs from workspace directories, so the lint-staged command passes the root ignore file explicitly.
The previous commit accidentally replaced the whole ignore file with the single migration entry — the original entries (dist, coverage, .astro, generated icons) are back, migration/ added on top. lint-staged runs prettier from workspace directories where the root .prettierignore is invisible, so the command now passes it explicitly.
Stacked PRs target the branch below them, and the pull_request branches filter matches the base — without these entries every layer above the bottom runs with no CI until the cascade retargets it. Temporary; removed when the stack lands.
librowski
force-pushed
the
token-usage-guard
branch
from
August 20, 2026 16:48
f92cf71 to
890d8bf
Compare
The base allowlist needed a new entry for each integration or stack branch and left dead entries behind; the default pull_request trigger covers them all. pr-check-docs keeps its paths filter.
piotrblaszczyk
approved these changes
Aug 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
DS 2.0 migration prep. Lands on
mainindependently of the Figma token export.Changes
var(--…)that resolved to nothing —--wb-→--ax-prefix typos across sdk and ai-studio stylesheets. Two names had no 1:1 token and were mapped by value (operator-wrap-gap→spacing-4,modal-l-content-gap-2→spacing-16; render preserved). Message neutral variant uses theme-aware--ax-txt-primary-default. Edge labels point at--ax-edge-primary-hover/-active; four consumer-less--wb-edge-color*variables removed. icon-switch: dead thumb-background declaration dropped. text-area: disabled background defined astransparent..stylelintrc.mjs):csstools/value-no-unknown-custom-properties— everyvar(--name)in workspace CSS must resolve; the definition set is collected bytools/stylelint/custom-properties.mjs(token dist + all source CSS). Variables set from JS carry in-placestylelint-disablecomments with the reason.wb/no-system-token-fallbacks(local rule) — no fallbacks on--wb-*/--ax-*; exceptions viastylelint-disable-next-line … -- reason.pnpm build:ui, in lint-staged, and inpnpm check;apps/docsexcluded viaignoreFiles.--wb-*prefix ownership convention inpackages/sdk/README.md; lint usage inpackages/tokens/README.md.Baseline: the same lint run against
mainreports 118 errors; this branch reports 0.Intended visual changes: variables-settings modal picks up its token colors/spacing/radii, edge-label hover/select colors come from tokens, log-panel badges use token gray instead of
#888.Lockfile note: adding the stylelint devDependencies also re-resolves stale transitive
typescriptpeer entries (5.9.3 → 5.6.3) that no declared range permits — a one-time correction.