Skip to content

Fix dangling --wb-* custom properties + token-usage guard - #83

Open
librowski wants to merge 21 commits into
mainfrom
token-usage-guard
Open

Fix dangling --wb-* custom properties + token-usage guard#83
librowski wants to merge 21 commits into
mainfrom
token-usage-guard

Conversation

@librowski

Copy link
Copy Markdown
Collaborator

DS 2.0 migration prep. Lands on main independently of the Figma token export.

Changes

  • Fix every 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-gapspacing-4, modal-l-content-gap-2spacing-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 as transparent.
  • Strip dead fallbacks on system tokens — the token always exists, so the fallback never wins; it only masks typos.
  • Add the token-usage lint (root .stylelintrc.mjs):
    • csstools/value-no-unknown-custom-properties — every var(--name) in workspace CSS must resolve; the definition set is collected by tools/stylelint/custom-properties.mjs (token dist + all source CSS). Variables set from JS carry in-place stylelint-disable comments with the reason.
    • wb/no-system-token-fallbacks (local rule) — no fallbacks on --wb-*/--ax-*; exceptions via stylelint-disable-next-line … -- reason.
    • Runs in CI after pnpm build:ui, in lint-staged, and in pnpm check; apps/docs excluded via ignoreFiles.
  • Docs--wb-* prefix ownership convention in packages/sdk/README.md; lint usage in packages/tokens/README.md.
  • Changesets — sdk patch; ui minor (new public TextArea variable).

Baseline: the same lint run against main reports 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 typescript peer entries (5.9.3 → 5.6.3) that no declared range permits — a one-time correction.

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