CORE-2720: Add a global CSS token file for theme values and sweep migrated CSS onto it - #143
Conversation
…ur syntax Addresses review on #143. theme.css is now generated rather than hand-written and kept in sync by a test (RoyEJohnson's suggestion). src/theme/themeCss.ts owns the projection from the JS theme into --ox-* custom properties; `npm run generate:theme-css` writes the file; tokens.spec.ts asserts the committed file equals the generator's output. That replaces the three "do these two agree" tests with one that cannot be partially satisfied, and it fixes the stale src/theme/theme.css.spec.ts reference in the header comment, which Copilot caught. The component-CSS colour check now parses declarations instead of grepping for hex. It resolves hex, the functional notations and bare named colours anywhere they appear — shorthands and gradient stops included — while descending into var()/color-mix()/gradients rather than treating them as literals. A translucent colour passes when its opaque channels are a theme value, so shadows keep working without allowlisting each alpha, but a new hue via rgba() is still refused. That lets #33 come off KNOWN_OFF_PALETTE. Also added: a check that every --ox-* a stylesheet reads actually exists. The checker has its own tests now — 28 cases covering what it must flag and what it must leave alone — so the guarantee is tested rather than asserted. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
efdc08b to
3ba2658
Compare
3ba2658 to
cbf780d
Compare
Stacked on #143, so these three components use the :root token file rather than binding theme values inline per component -- the same sweep #143 applied to everything already migrated. - SidebarNav/ButtonNav/Pagination CSS now reads var(--component-hook, var(--ox-token)), and the inline CSSPropertiesWithVariables objects are gone. - The sidebar backdrop z-indexes stop being literals. That caveat only existed because component-scoped custom properties inherit down the tree and the backdrop rules target siblings of the nav; :root tokens reach siblings fine, so these are now calc(var(--ox-z-index-navbar) + 1) and calc(var(--ox-z-index-sidebar) - 1). - #959595 on the toggle button border is genuinely off-palette, carried over verbatim from the styled-components original, so it goes in KNOWN_OFF_PALETTE with a reason rather than being snapped to neutralMedium, which would be a visual change rather than a refactor. The three "binds theme values as custom properties" tests are dropped: there is no inline binding left to assert, and tokens.spec.ts now checks the theme wiring centrally. Replaced where a public contract survives -- that consumers can still override through the documented --sidebar-nav-* / --pagination-* hooks. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Stacked onto #137 as asked. Base is now Pre-rebase SHA was The overlap was real, and one part of it needed a decision
TreeCheckbox merged cleanly in substance. #137 wraps the style object in NavBarMenuButtons is where they genuinely collide. This PR removes every custom property that component set, so after the sweep there is nothing left for That made three of #137's new tests fail — the ones asserting the component still sets its own variables inline: Each failed on an Flagging it prominently because it is me editing tests from your PR. If you'd rather keep those assertions and have the NavBar variables stay in JS, say so and I'll reverse that part — it's a one-file change. #140 came alongIts base was this branch, so rewriting my history would have left it showing a garbage diff. I rebased it onto the new head and force-pushed ( Worth knowing: GitHub refused the base change outright — "Cannot change the base branch because the pull request is part of a stack" — because #143 and #140 had been auto-grouped into stack #144. I dissolved that grouping with Verification
|
This comment was marked as resolved.
This comment was marked as resolved.
RoyEJohnson
left a comment
There was a problem hiding this comment.
Resolve the conflicts
…ur syntax Addresses review on #143. theme.css is now generated rather than hand-written and kept in sync by a test (RoyEJohnson's suggestion). src/theme/themeCss.ts owns the projection from the JS theme into --ox-* custom properties; `npm run generate:theme-css` writes the file; tokens.spec.ts asserts the committed file equals the generator's output. That replaces the three "do these two agree" tests with one that cannot be partially satisfied, and it fixes the stale src/theme/theme.css.spec.ts reference in the header comment, which Copilot caught. The component-CSS colour check now parses declarations instead of grepping for hex. It resolves hex, the functional notations and bare named colours anywhere they appear — shorthands and gradient stops included — while descending into var()/color-mix()/gradients rather than treating them as literals. A translucent colour passes when its opaque channels are a theme value, so shadows keep working without allowlisting each alpha, but a new hue via rgba() is still refused. That lets #33 come off KNOWN_OFF_PALETTE. Also added: a check that every --ox-* a stylesheet reads actually exists. The checker has its own tests now — 28 cases covering what it must flag and what it must leave alone — so the guarantee is tested rather than asserted. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
c466a0a to
7f8bdfb
Compare
Stacked on #143, so these three components use the :root token file rather than binding theme values inline per component -- the same sweep #143 applied to everything already migrated. - SidebarNav/ButtonNav/Pagination CSS now reads var(--component-hook, var(--ox-token)), and the inline CSSPropertiesWithVariables objects are gone. - The sidebar backdrop z-indexes stop being literals. That caveat only existed because component-scoped custom properties inherit down the tree and the backdrop rules target siblings of the nav; :root tokens reach siblings fine, so these are now calc(var(--ox-z-index-navbar) + 1) and calc(var(--ox-z-index-sidebar) - 1). - #959595 on the toggle button border is genuinely off-palette, carried over verbatim from the styled-components original, so it goes in KNOWN_OFF_PALETTE with a reason rather than being snapped to neutralMedium, which would be a visual change rather than a refactor. The three "binds theme values as custom properties" tests are dropped: there is no inline binding left to assert, and tokens.spec.ts now checks the theme wiring centrally. Replaced where a public contract survives -- that consumers can still override through the documented --sidebar-nav-* / --pagination-* hooks. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Resolved — The cause was that #137 was force-pushed (
The one real conflict#139 landed on Resolved by taking the deletion. This is the good outcome I'd flagged when we discussed ordering: with #139 in first, that part of this PR's diff simply disappears rather than being churn that gets thrown away. #139's replacement spec asserts behaviour directly and touches no styles, so there was nothing to carry over. Net effect here is one fewer changed file. Everything else replayed clean. One thing you should know before merging the stack#137 is one commit behind Two consequences:
Rebasing #137 onto current Verification
|
Follows the CORE-2720 (#143) sweep, which this branch is now stacked on. The two new stylesheets repeated eleven palette hexes as var() fallbacks; they now read the --ox-* tokens instead, e.g. color: var(--help-menu-button-color, var(--ox-color-gray)); The override hooks are unchanged -- only their defaults moved from JavaScript to the CSS side, so the components no longer bind static custom properties inline. That means style is no longer destructured in ProfileMenuButton, ProfileMenuItem, HelpMenuButton or HelpMenuItem: it passes through in ...props and react-aria handles both the object and render-callback forms itself. Two consequences worth naming: - The CORE-2710 (#137) dependency is gone rather than deferred. The bug it guards against was a wrapper overwriting the caller's style, which these wrappers no longer do, so the menu items need nothing from #137. Same reasoning as the note #143 leaves on NavBarMenuItem. - iframeWrapperStyle and putAwayStyle are gone; the iframe wrapper and the put-away bar take their colours from HelpMenu.css. className composition stays -- that one is a real bug fix, not a default. The specs that asserted the inline defaults now assert what matters instead: the caller's style reaches the element in both forms, and the override hook still wins. Defaults are covered centrally by src/theme/tokens.spec.ts, which also fails on any colour literal that duplicates a theme value -- both new stylesheets pass it. Also carries CORE-2715 (#138) as a cherry-pick: it is on main but not yet in this base, and without it the old flaky ProfileMenu snapshot fails against the migrated component. It drops out as a duplicate when #143 rebases onto main. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Theme values were being copied into CSS by hand — 86 hex literals across the 22 migrated stylesheets, in inconsistent casings, with three var() fallbacks already drifted from the JS values they duplicated (caught in review on #130, not by CI). src/theme/theme.css projects the JS theme into --ox-* custom properties. palette.ts stays the source of truth; tokens.spec.ts fails the build if the two disagree, if a stylesheet repeats a theme value as a literal, or if it introduces a colour that is neither a theme value nor on the KNOWN_OFF_PALETTE allowlist. Static colours no longer travel through React inline styles. The --component-* override hooks stay, with their defaults moved to the CSS side as var(--component-x, var(--ox-color-y)); only genuinely dynamic bindings (variant lookups, navbar sizing, disabled opacity) remain in JS. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ur syntax Addresses review on #143. theme.css is now generated rather than hand-written and kept in sync by a test (RoyEJohnson's suggestion). src/theme/themeCss.ts owns the projection from the JS theme into --ox-* custom properties; `npm run generate:theme-css` writes the file; tokens.spec.ts asserts the committed file equals the generator's output. That replaces the three "do these two agree" tests with one that cannot be partially satisfied, and it fixes the stale src/theme/theme.css.spec.ts reference in the header comment, which Copilot caught. The component-CSS colour check now parses declarations instead of grepping for hex. It resolves hex, the functional notations and bare named colours anywhere they appear — shorthands and gradient stops included — while descending into var()/color-mix()/gradients rather than treating them as literals. A translucent colour passes when its opaque channels are a theme value, so shadows keep working without allowlisting each alpha, but a new hue via rgba() is still refused. That lets #33 come off KNOWN_OFF_PALETTE. Also added: a check that every --ox-* a stylesheet reads actually exists. The checker has its own tests now — 28 cases covering what it must flag and what it must leave alone — so the guarantee is tested rather than asserted. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Roy's follow-up: "It would have to be part of the build process." scripts/build.bash now runs scripts/generate-theme-css.bash as its first step, so the file is regenerated before either tsc pass and before the rsync that copies it into dist/esm and dist/cjs. scripts/publish.bash goes through build:clean, so a published package cannot ship a stale theme.css even if the committed copy drifted. The file stays committed as well as generated: jest and ladle read src/ directly and never run the build, and CI runs lint and test rather than build. The freshness check in tokens.spec.ts is what catches a stale copy there — the build regenerating it and the spec failing on it cover different paths, so both are needed. Verified by corrupting src/theme/theme.css: the spec fails, `npm run build` restores it, and both dist trees get the 48 tokens. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
css variables, too
Both from Copilot's second review. Removing the var() short-circuit in 635f854 left `tokenised` with no writer, so the field on Color and the `tokenised ||` guard in colorProblems were dead. Gone — a pure no-op, since an unset optional was always falsy. Added a case locking in the behaviour that replaced it: rgba(var(--channels), 0.2) is flagged rather than skipped, because we cannot tell what colour it is and skipping would let an off-palette value through. themeValues was built with `describeColor(...).hex as string`. The cast is compile-time only, so a theme colour the parser could not reduce to channels would have entered the map under a null key and quietly stopped being recognised — every stylesheet using it would then report it as off-palette, a long way from the cause. The map now filters unresolvable entries out and a spec asserts there are none, so the failure names the offending entry instead. Verified by pointing palette.red at oklch(): the suite fails with "--ox-color-red: oklch(63% 0.19 25)" rather than misbehaving downstream. 342 tests pass; typecheck, lint and build:clean clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both were reported on this PR after Copilot raised them on the rex-web sibling (rex-web#3133); the checker there is the same design. 1. parseHex validated the expanded length rather than the digits, so '#ggg' expanded to 'gggggg', passed the length test and came back as a colour. That defeated unresolvableThemeColors, whose whole job is to stop a malformed palette value entering themeValues under a key nothing can match — every use of that colour would then have read as off-palette, a long way from the cause. Now checked against the hex grammar before parsing. 2. The declaration walk discarded the property, so any identifier that happens to be a CSS named colour was read as one: 'animation-name: red' reported as off-palette, 'font-family: white' as duplicating --ox-color-white with a suggested fix that would break the declaration. The walk now returns the property, and a bare identifier is only read as a colour where one can go — a custom property, anything with 'color' in the name, the border family, or one of the colour-bearing shorthands, vendor prefixes stripped. Only bare identifiers are gated. Hex and the colour functions are only ever colours, so they stay in scope everywhere, including 'animation-name: #d5d5d5'. Both were latent — no CSS in the repo triggers either — but (2) would have bitten the first component that animates something named after a colour. Tests were written failing first: the four new cases reproduce the defects on the old code. Added cases pinning that the property gate did not weaken detection in real colour positions (custom property, box-shadow, vendor-prefixed, gradient stop). 353 tests pass; typecheck, lint and build:clean clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Consequence of stacking this onto #137. Three of that PR's new tests asserted the component still sets its own --navbar-menu-item-* / --navbar-popover-border-color inline (`expect(...).toBeTruthy()`), which is exactly what this PR moves into NavBarMenuButtons.css. The assertions on the vanished inline defaults are gone; everything else in those tests stays. What CORE-2710 was actually protecting — that a caller's style reaches the element in both the object and render-callback forms — is still asserted, and tokens.spec.ts now guards the defaults centrally. Comments in place pointing at where the defaults live now, so the next reader does not think the coverage was simply dropped. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
7f8bdfb to
f9cf833
Compare
Stacked on #143, so these three components use the :root token file rather than binding theme values inline per component -- the same sweep #143 applied to everything already migrated. - SidebarNav/ButtonNav/Pagination CSS now reads var(--component-hook, var(--ox-token)), and the inline CSSPropertiesWithVariables objects are gone. - The sidebar backdrop z-indexes stop being literals. That caveat only existed because component-scoped custom properties inherit down the tree and the backdrop rules target siblings of the nav; :root tokens reach siblings fine, so these are now calc(var(--ox-z-index-navbar) + 1) and calc(var(--ox-z-index-sidebar) - 1). - #959595 on the toggle button border is genuinely off-palette, carried over verbatim from the styled-components original, so it goes in KNOWN_OFF_PALETTE with a reason rather than being snapped to neutralMedium, which would be a visual change rather than a refactor. The three "binds theme values as custom properties" tests are dropped: there is no inline binding left to assert, and tokens.spec.ts now checks the theme wiring centrally. Replaced where a public contract survives -- that consumers can still override through the documented --sidebar-nav-* / --pagination-* hooks. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Rebased onto the current #137 head to clear the conflicts that were blocking this and #140. This branch was still carrying a stale copy of #137's commit ( Replayed the ten commits here onto the real #137, dropping the stale duplicate:
368 tests pass on the new base (40 suites, no failures), typecheck and lint clean, checks green, and this now reports |
Follows the CORE-2720 (#143) sweep, which this branch is now stacked on. The two new stylesheets repeated eleven palette hexes as var() fallbacks; they now read the --ox-* tokens instead, e.g. color: var(--help-menu-button-color, var(--ox-color-gray)); The override hooks are unchanged -- only their defaults moved from JavaScript to the CSS side, so the components no longer bind static custom properties inline. That means style is no longer destructured in ProfileMenuButton, ProfileMenuItem, HelpMenuButton or HelpMenuItem: it passes through in ...props and react-aria handles both the object and render-callback forms itself. Two consequences worth naming: - The CORE-2710 (#137) dependency is gone rather than deferred. The bug it guards against was a wrapper overwriting the caller's style, which these wrappers no longer do, so the menu items need nothing from #137. Same reasoning as the note #143 leaves on NavBarMenuItem. - iframeWrapperStyle and putAwayStyle are gone; the iframe wrapper and the put-away bar take their colours from HelpMenu.css. className composition stays -- that one is a real bug fix, not a default. The specs that asserted the inline defaults now assert what matters instead: the caller's style reaches the element in both forms, and the override hook still wins. Defaults are covered centrally by src/theme/tokens.spec.ts, which also fails on any colour literal that duplicates a theme value -- both new stylesheets pass it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Summary
Follows up on Beth's review comment on #130: "it might be good to move theme variables we want to keep using (like the color palette) to a global css file that it can reference … seems like we could end up with a lot of hardcoded colors, spacing, etc."
She was right, and the evidence was already in the migrated files. Before this PR, the 22 migrated stylesheets contained 86 hardcoded hex literals, nearly all of them palette values re-typed by hand:
palette.darkRedin four files in two casings;palette.paleRedas both#FBE7EAand#fbe7eapalette.whiteas#ffffff(16×),#fff(4×), and the bare keywordwhite(2×)var()fallbacks that had already diverged from the JS values the component was binding. Nothing in CI would have caught them.What changed
src/theme/theme.css— a:rootblock projecting the JS theme into--ox--prefixed custom properties (palette,colors.link,zIndex,padding.navbar). Prefixed so it can't collide with a consuming app's variables. Generated, not written:src/theme/themeCss.tsowns the projection andscripts/generate-theme-css.bashwrites the file, as the first step ofscripts/build.bash(and so ofpublish.bash, viabuild:clean). It is committed as well as generated, because jest and ladle readsrc/directly and CI runslint/testrather thanbuild— the build covers the published artifact, the spec below covers everything else.src/theme/tokens.spec.ts— the part that makes this stick. Fails the build if:theme.cssis not what the generator produces from the JS themeKNOWN_OFF_PALETTEallowlist--ox-*token that does not existAdding a new colour is therefore deliberate: put it in
palette.ts, or in the allowlist with a reason.The colour check parses declarations rather than grepping for hex, so it covers every syntax a colour can be written in — hex,
rgb()/hsl()/oklch()/color(), and bare named colours wherever they appear, shorthands and gradient stops included. Functions that merely contain colours (var(),color-mix(), the gradients) are descended into rather than treated as literals. A translucent colour passes when its opaque channels are a theme value —rgba(0, 0, 0, 0.2)is black at 20% and has no token form — which still refuses a new hue smuggled in throughrgba(). The checker has its own tests (40 cases, what it must flag and what it must leave alone), so the guarantee above is tested rather than asserted.Four orphan colours moved into
palette.ts.#be3c08,#b03808,#646464and#4c4c4cwere string literals intheme/buttons.tswith nothing recording that they're hover/active variants ofpalette.orangeandpalette.darkGray. They're noworangeHover,orangeActive,darkGrayHover,darkGrayActive, grouped under a// button variantscomment — purely additive to the published palette. (Roy renamed these from my originaldarkOrange/darkerOrange/mediumGray/darkerGrayincbf780d; his names say what the colours are for rather than just where they sit on a lightness ramp, which is the better call.)All 22 stylesheets swept onto tokens, including inside
var()fallbacks.Static colours no longer travel through React inline styles. The
--component-*override hooks stay exactly as they were — only their defaults moved to the CSS side:Genuinely dynamic bindings stay in JS: button/checkbox variant lookups, navbar height and
maxWidth, disabled opacity, the dropdown caret colour.README gained a Styling section documenting the pattern, so the remaining ~29 files are migrated against tokens rather than against hand-copied literals.
Two things worth a closer look
1. A latent bug fixed in passing.
--button-shadowis shared byButton.cssandDropdownMenu.css, and the JS bindspalette.blackfor all three variants. Button's fallback had drifted to#424242(neutralDarker) while DropdownMenu's was#000000. Unreachable today because the JS always sets the variable, so this is a zero-visual-change fix — but the two files would have rendered the same variant differently if it were ever reached.2. One edge-case behaviour change. Removing an inline default changes who wins the cascade. If a consumer set, say,
--tabs-border-coloron an ancestor element via their own stylesheet, the inline default used to beat it; now the ancestor's value applies. That is arguably the fix rather than the regression, and passingstyle={{'--tabs-border-color': ...}}to the component itself — the documented override path, covered by specs — is unaffected. Flagging it because it is the only way this refactor is observable from outside.Verification
npm test— 365 passed, 40 suites, 115 snapshots. 45 snapshots regenerated; every diff is an inlinestyleattribute losing a static custom property. No DOM structure changes.npm run typecheckand eslint over all changed files — clean.npm run build— succeeds;theme.csslands in bothdist/esm/theme/anddist/cjs/theme/, and the side-effect imports survive asimport '../theme/theme.css'(ESM) andrequire("../theme/theme.css")(CJS).tokens.spec.tsas what now guards the defaults.mainwith Playwright at 1280×800, animations paused, then compared. 100/105 pixel-identical. The 5 that differ (loader--default,loader--large,error-modal--default,forms--data-references-in-namespaces,sidebar-nav--using-body-portal) differ by the same amount whenmainis captured twice and diffed against itself, so they are animation-frame and timestamp nondeterminism, not this change. That control run is the reason I trust the other 100.A pre-existing flake, now fixed upstream.
ProfileMenu › matches snapshot with user initialsfailed 3/3 runs with a cold jest cache, ondata-focus-visible/data-focusedbeing absent from the trigger — react-aria's focus state is timing-sensitive and the snapshot captured it. I first hit it whenjest -ustripped those attributes and reddened a push (restored in542b66e3), and originally wrote it up as an environment quirk of my machine; that was wrong, it reproduced onmainindependently of this branch.#138 has since landed on
mainand replaces that snapshot with targeted assertions, which is the proper fix. It is not in this stack yet — see the note below — so a cold-cache run here still hits it.Plumbing note
scripts/build.bashrsyncs.css1:1 with no CSS bundler, so a CSS@importwould be at the mercy of each consumer's resolver. Component.tsxfiles importtheme.cssalongside their own stylesheet instead — same pattern already in use, covered by the existingsideEffectsentry, and no action needed from consuming apps.Review follow-ups
Both threads on the first review are addressed in
b9657d7, which touches only the theme plumbing — no component CSS or snapshots changed, so the pixel-diff evidence above still holds.theme.cssfrom the JS theme. Done, as described above. Removes the class of mistake rather than detecting it: you can no longer add a palette entry and forget the CSS. The one deliberate loss is the per-token trailing comments (/* darkGray, hover */), which would have needed either scrapingpalette.tssource or a second copy of the notes; they remain on the palette entries themselves.#00000033came off the allowlist as a result — it now passes on the alpha rule instead of by exception, leaving just the two genuinely off-palette greys.Second review, addressed in
f12703b:build.bashnow regeneratestheme.cssbefore eithertscpass and before the rsync intodist/. Verified by corrupting the file: spec fails,npm run buildrestores it, both dist trees get the 48 tokens. ~1.7s on a build that already runstsctwice.theme.tsisn't pure data (zIndexis computed,defaultFocusOutlineis a CSS fragment), so a data file would split the source of truth rather than centralise it; andpalette.tsis published API whoseas constliteral types and per-entry comments consumers rely on. It is a cheap change to make later if the palette ever needs a non-TS consumer —themeCss.tsis the only thing that would move.Third review, addressed in
652ed43:as stringcasts ondescribeColor(...).hex. Right, and the more dangerous of the two, because the cast is compile-time only so nothing would have thrown. An unresolvable theme colour would have enteredthemeValuesunder anullkey and silently stopped being recognised — every stylesheet using it would then report it as off-palette, a failure a long way from its cause. The map now filters unresolvable entries out and a spec asserts there are none. Verified by pointingpalette.redatoklch(): the suite fails naming--ox-color-redinstead of misbehaving downstream.tokenisedflag. Also right, as a consequence of Roy removing thevar()short-circuit in635f854. Field and guard removed; a no-op, since an unset optional was always falsy. Added a case pinning the behaviour that replaced it —rgba(var(--channels), 0.2)is asserted to be flagged rather than skipped, matching the reasoning in Roy's comment.Fourth round — two defects I found and reported myself, fixed in
08ee93a. Both surfaced while answering a review question on the rex-web sibling (#3133), where Copilot raised them; the checker there is the same design. Tests were written failing first, so both are demonstrated rather than asserted.parseHexvalidated the expanded length, not the digits.#gggexpanded togggggg, passed the length test and came back as a colour — defeatingunresolvableThemeColors, whose whole job is to stop a malformed palette value enteringthemeValuesunder a key nothing can match. Now checked against the hex grammar first.animation-name: redreported as off-palette,font-family: whiteas duplicating--ox-color-whitewith a suggested fix that would break the declaration. The walk returns the property now, and a bare identifier is only read as a colour where one can go. Only bare identifiers are gated — hex and the colour functions stay in scope everywhere, includinganimation-name: #d5d5d5. Four cases pin that the gate didn't weaken real detection.Both were latent — nothing in this repo's CSS triggers either — but the second would have bitten the first component that animates something named after a colour.
Stacked on #137
Base is
CORE-2710-compose-render-props-style, per Roy's request. Rebased rather than merged, so history stays linear.The two overlapping files resolved in opposite directions:
Tree/TreeCheckbox.tsxmerged in substance — CORE-2710: Compose render-callback style in react-aria-components wrappers #137'scomposeRenderPropswrapper kept, carrying only the bindings this PR leaves in JS. All of CORE-2710: Compose render-callback style in react-aria-components wrappers #137's TreeCheckbox tests pass untouched.NavBarMenuButtons.tsxgenuinely collides. This PR removes every custom property that component set, so nothing is left forcomposeRenderPropsto mergestylewith;styleis no longer destructured and passes through in...props, where react-aria handles both forms. Three of CORE-2710: Compose render-callback style in react-aria-components wrappers #137's tests asserted the inline defaults this PR deletes (expect(...).toBeTruthy()on--navbar-menu-item-*/--navbar-popover-border-color). Those assertions are removed and the rest of each test kept, so the callback-vs-object contract is still covered andtokens.spec.tsguards the defaults. This is me editing tests from another PR — worth a look, and trivially reversible if the preference is to keep those variables in JS.#140 was based on this branch, so it was rebased onto the new head (
3973291→6194fd1) and its base restored; its content is unchanged and 380 tests pass there. GitHub blocked the base change until the auto-created stack #144 was dissolved withgh stack unstack; #137/#141's stack was not touched.Keeping up with the base
#137 was force-pushed onto a newer
main, so this branch was rebased onto its new head (c466a0af→7f8bdfb3).#139 landed on
mainand deletesHelpMenu/__snapshots__/index.spec.tsx.snap, which this PR edited because the sweep changed values inside it — a modify/delete conflict, resolved by taking the deletion. That is the ordering outcome predicted when this was planned: with #139 in first, this part of the diff disappears instead of being churn thrown away later. One fewer changed file here.#138 is queued to do the same to the ProfileMenu snapshot. #137's base is
c6ed1cd8(#139's merge), one commit behindmain, so it does not yet include #138. This PR still edits that snapshot — correctly, since the file is live at its current base — and will hit the identical conflict once #137 catches up, resolved the same way (take the deletion, which also makes542b66e3moot). Rebasing #137 onto currentmainclears that and the flaky test with it; not done here because #141 is also based on #137 and would have to move too.Sequencing
This wants to land ahead of the remaining migration subtasks. Done now, the remaining ~29 files are written against tokens at no extra cost; done at the end, all 51 get re-touched in a second pass of pure find-and-replace noise. #140 (CORE-2005) has already adopted the tokens and is stacked on this PR. #141 (CORE-2006) sits alongside this PR on #137 and will need a small follow-up to adopt them.
Related
🤖 Generated with Claude Code