refactor: migrate Chip (next) colours to beta tokens - #5225
Conversation
|
@claude review |
|
Claude finished @pomfrida's task in 3m 43s —— View job Review — Chip (next) beta token migrationRead the full Verdict: clean, well-scoped migration. The ✅ Verified
🟡 Questions / nits
Everything else (focus ring retarget to
|
|
Re. review point 1 (text colour on default/outlined moving from The absolute step-12 values differ marginally because the whole beta palette is regenerated, but that applies to every step and is covered by the visual parity check against prod (see PR description). Points 2 ( |
|
Correction to the parity claim above: the visual check against prod turned out to only cover light mode for Chip (dark was compared local-only). I've now completed the dark-mode comparison against prod with computed colours, and it is not full parity: Matches in dark
Deviations in dark
Items 1–3 are token-export issues rather than mapping mistakes — the PR deliberately follows the semantic subtle ladder. Flagged in #5221 for the token/design side. Whether this PR should stay on the semantic ladder (and let the fix land in the tokens) or pin steps per scheme is a design call. |
…th the widened semantic block The widened semantic layer and the color-scheme scope rules both apply to [data-color-scheme] elements at equal specificity, so source order decides the three duplicate names tracked in #5221. With the previous alphabetical order the semantic block sorted last and won - and its --eds-border-focus is a self-reference, computing to the guaranteed-invalid value, which would have dropped focus outlines for the incoming Chip (#5225) and Button (#5222) migrations inside scoped subtrees (both use var(--eds-border-focus) for their focus ring). The bundler now ranks color-scheme/* after every other layer, so the scheme-specific values win on scoped elements and every resolved value matches the pre-widening state. Verified in the browser: --eds-border-focus resolves to the light/dark blue per subtree, and text-disabled/border-disabled keep their scheme values.
…#5239) * fix: emit the beta semantic token layer under the color-scheme scopes The Tokens Studio CSS export declared the semantic layer at :root while the scale aliases it references only exist under [data-color-scheme] scopes. Custom properties substitute where they are declared, so the semantic tokens resolved once at the root and never re-resolved inside [data-color-scheme] subtrees, breaking subtree colour-scheme switching (ADR-0004/ADR-0013). The saved EDS-CSS export configuration now sets rootSelector: ':root, [data-color-scheme]' (was the ':root' default), so every non-dimensional layer is also declared on any element carrying the attribute and var() references substitute against the nearest scope. Token content is unchanged - the diff is selector lines only. The <html>-mirror workaround in the Storybook decorator is no longer needed and is removed. Closes #5226 * chore: use beta semantic tokens for the storybook wrapper canvas The wrapper used the legacy --eds-color-bg-neutral-surface, which has no dark declaration in the 2.x bundle, so the story canvas stayed light in dark mode. The beta semantic tokens re-resolve per [data-color-scheme] subtree after the rootSelector change, so the canvas now follows the toolbar toggle. Legacy is left untouched - it is being replaced, not maintained. * fix: widen only the semantic layer to [data-color-scheme] Review follow-up on #5239. Widening every non-dimensional layer via the export's global rootSelector regressed the density cascade: the density base (comfortable) declares the same --eds-density-* names as the compact/relaxed variants, so re-declaring it on every [data-color-scheme] element clobbered a [data-density] ancestor's values for the whole subtree. The export format has no per-layer selector, so the saved EDS-CSS configuration is reverted to the default rootSelector (:root) and the semantic layer - the only layer that references the scheme-scoped scale aliases - is widened repo-side by scripts/widen-semantic-scope.mjs, chained before generate-css-bundle.mjs in the generate:css-bundle package script so the release workflow needs no change. The script is idempotent and fails loudly if the export layout changes. Also drops a comment reference to ADR-0013 (not merged yet, PR #5200) and documents the #5221 name-collision caveat in the bundle header. * chore: assert the semantic layer is widened before bundling The widen step is chained in the generate:css-bundle package script, but running the bundler directly would silently bundle an unwidened semantic layer and regress subtree colour-scheme switching (#5226). The bundler now fails loudly instead. * chore: harden the semantic-widening against formatting and export drift Review follow-up on #5239, round two. - The widened selector is matched with whitespace-tolerant regexes and emitted in Prettier's canonical one-selector-per-line form, shared between the widen script and the bundler via semantic-scope.mjs, so a prettier --write no longer breaks the pipeline with a misleading 'export layout changed' error. - Every semantic/*.css file is widened and asserted, mirroring the bundler's directory glob - a file the export adds later cannot slip through with the narrow :root selector. - src/tokens/* is added to .prettierignore (root and package-local): the directory is machine output and was never Prettier-conformant (the export emits double-quoted attribute selectors and no trailing newline, failing prettier:check on main too), and hand-formatting it would be reverted by the next export run. The package prettier:check now passes. * chore: widen nested semantic files and document the widening in the release workflow Review follow-up on #5239, round three. - The widen script now globs semantic/ recursively, matching the bundler's assertion glob - a nested file the export adds later gets widened instead of deadlocking the pipeline with a remedy message that is a no-op. - A selector that matches the tolerant regex but not the canonical form is normalised, so the committed bytes are a function of content only. - The release workflow's bundle step and auto-PR body now mention the semantic-layer widening, so the selector diff in tokens-release PRs is traceable to #5226 instead of looking like an export change. * fix: concatenate the color-scheme layer last so it wins collisions with the widened semantic block The widened semantic layer and the color-scheme scope rules both apply to [data-color-scheme] elements at equal specificity, so source order decides the three duplicate names tracked in #5221. With the previous alphabetical order the semantic block sorted last and won - and its --eds-border-focus is a self-reference, computing to the guaranteed-invalid value, which would have dropped focus outlines for the incoming Chip (#5225) and Button (#5222) migrations inside scoped subtrees (both use var(--eds-border-focus) for their focus ring). The bundler now ranks color-scheme/* after every other layer, so the scheme-specific values win on scoped elements and every resolved value matches the pre-widening state. Verified in the browser: --eds-border-focus resolves to the light/dark blue per subtree, and text-disabled/border-disabled keep their scheme values.
fad4bf3 to
fa5aca8
Compare
|
Converted to draft after massive tokens change today - needs updating |
|
Re-verified against local Storybook after the token realignment (4a813cc, merged main in first so the branch has the renamed tokens). Quick background for readers without token context: every colour (neutral, accent, danger, …) comes as a row of 15 numbered shades, from lightest to darkest. The chip just picks shade numbers — shade 2 for the resting fill, 3 for hover, 4 for pressed — the same numbers the designers' own semantic tokens point to.
Holding this in draft until #5282 is resolved — the beta components are actively being tested, and dark mode shouldn't go out looking broken. |
|
Update after today's push: Chip is now on the semantic Good news on #5283: the success/info interactive tokens have landed in Tokens Studio and are in #5284. Their values are identical to the raw steps Chip mirrors in the meantime, so once #5284 merges the swap is a pure rename. One new thing that needs a design call: |
|
Regarding #5283, we are not using interactive colors on the Chip text, me and Edvard dont see the use for it right now, but can change later if we were wrong. We are using static --eds-text-success (etc.) for the text colors, since the text dont change on hover/pressed, just the background color. Its updated in figma with the new success and info colors from #5284 which we merged in yesterday. Just fyi, I did write the same but a bit longer explanation on #5283 as well, so we have track of the decisions both places. |
e02ed8d to
8a5838a
Compare
Follows the Button pattern (#5222): background-interactive-{tone}-{muted,emphasis}-*, text-interactive-{tone}-default, border-interactive-{tone}-emphasis-default, and border-interactive-focus for the focus ring. Neutral maps text to --eds-text-primary (no interactive neutral text/icon by design, #5283). success/info have no interactive group yet (#5283) and stay on raw steps mirroring the semantic ladders.
…ractive
Use --eds-text-{tone} for label text and --eds-icon-{tone} for icons — the
two tokens differ for accent (shade 12 vs 10) and are semantically distinct
for all tones. Renames --_text-interactive to --_text and adds --_icon per
tone. High-contrast variant now overrides --_text/--_icon variables instead
of setting color directly.
8a5838a to
e57aaaa
Compare
|
Rebased onto beta.6 (tokens-studio-release #5331) — both original blockers are now resolved: #5282 (non-monotonic dark scale): The dark neutral palette is now monotonic. Steps 3–6 progress correctly in lightness (0.47 → 0.52 → 0.58 → 0.595), so hover and pressed no longer jump unexpectedly. #5287 (neutral chip invisible on canvas): Also updated text and icon tokens to use the separate |
|
@claude review |
|
Claude finished @millus's task in 7m 58s —— View job Review — Chip (next) beta token migrationRead the full Verdict: correct and well-scoped. Every token resolves, the ladder values match the PR description exactly, the tone-slot indirection is clean, and the "migrates completely" claim holds. Findings below are one accessibility gap worth closing before merge and a set of nits. ✅ Verified
🟠 Worth closing before merge1. The contrast verification only covers resting states. Label text stays at step 12 while the fill walks 3 → 4 → 5, so contrast strictly decreases on hover and pressed in both schemes. Danger, read from
WCAG 1.4.3 applies to text in hover/active states, and the PR already reports resting danger at Lc 74.4 — below the Lc 75 target before the ladder starts eating into it. Extending the APCA table to hover + pressed (danger and warning at minimum) would either close this or produce a second token-level issue alongside #5335. Not a 2. High-contrast text depends on source order, not specificity. 🔵 Nits
Not verifiedI could not run the Jest suite:
|
Closes #5223. Part of #5119 (phase 1 — colour). Second component onto the Tokens Studio beta tokens, following the Button test case (#5222). Chip has no disabled state, so it migrates completely — no legacy colour references remain.
Changes
chip.cssonly. All six tones consume the semantic*-interactive-*groups via--_slots;data-color-appearanceswitches the tone at the chip root, with neutral as the default fallback.background-interactive-{tone}-{muted,emphasis}-{default,hover,pressed}for all three variants × all six tones. Success and info groups landed in beta.6 (feat: update tokens from Tokens Studio release #5284), resolving the interim workaround.--eds-text-{tone}(step 12 for all tones after beta.6). Neutral maps to--eds-text-primary— the interactive group has no neutral text variant by design (Semantic interactive tokens are missing success and info tones #5283). Static tokens are used because chip label colour does not change on hover/pressed; decision documented in Semantic interactive tokens are missing success and info tones #5283.--eds-icon-{tone}(step 10 for all tones). Icon and text intentionally differ; tracking in Semantic content tokens: icon/text interactive ladders disagree, and text.accent is off-scale #5330.--eds-border-interactive-{tone}-emphasis-default.--eds-border-interactive-focus(was--eds-border-focus), matching Button.--eds-text-on-emphasis/--eds-icon-on-emphasis.Visible changes from the legacy token mapping (design-authored, not local choices):
background-interactive-*-muted-default(was temporarily step 1 before the neutral token fix in beta.6 — Semantic neutral muted rest fill equals canvas — filled components become invisible #5287 resolved).border-interactive-*-emphasis-default(step 9).--eds-icon-{tone}(step 10) vs--eds-text-{tone}(step 12). Legacy had no icon-specific colour.Resolved blockers
background-interactive-neutral-muted-defaultnow points to neutral-3.Learnings
selectedhas no colour styling in Chip (check icon only), so the semantic selected groups (background-interactive-*-selected-*) were not exercised here — a later component or a Chip design update needs to validate those.Verification
text-on-emphasis/emphasis-defaulttoken pairing falls below Lc 75 (APCA) #5335.ToneVariantMatrix: resting chips clearly visible, hover/pressed ladder progresses correctly, high-contrast readable.