Rebrand: CADS color tokens under codeai-next, legacy-token bridge, codeai-audit pink brand#73701
Conversation
…ge, pink audit brand Ships the CADS (CodeAI Design System) color ramp behind data-brand='codeai-next' without touching what legacy-brand users see, so the rebrand can be QA'd in production ahead of the cutover and flipped on via the default-brand DCDO key. The CADS exports (colors_codeAi.css, primitiveColors_codeAi.css) change the token schema, not just values: --borders-* becomes --border-*, the aqua/teal/purple brand families collapse into one brand family, ramp steps extra-light/light become light/mid, and disabled/selected/alpha families are new. Several primitive names (e.g. --brand-purple-50, --neutral-base-black) exist in both schemas with different values, so the canonical files cannot load at :root before cutover. Instead: - brandCodeAiNext.css (generated by scripts/generateBrandCodeAiNext.mjs) rescopes the canonical files under [data-brand='codeai-next']. - brandCodeAiNextAliases.css maps every legacy token name onto its CADS successor in that scope, so unmigrated call sites are rebranded too. - brandLegacyShim.css defines the CADS-only names under legacy brands, so call sites can migrate to CADS names before cutover. - brandOverrides.css aggregates the above; imported after colors.css by the four style entry points. The all-pink audit ramp moves from colors.css (where it occupied codeai-next) to brandCodeAiAudit.css under a new codeai-audit brand code, added to Cdo::Brand and apps/src/util/brand.ts. CodeaiTheme (MUI) gets the real CADS purple palette; the pink placeholder palette becomes CodeaiAuditTheme for the audit brand. Verified: every legacy semantic/primitive token resolves under codeai-next, every CADS token resolves under legacy brands, all var() chains resolve within their scope, and cascade spot-checks pass on nested data-theme='Dark' subtrees (custom properties inherit as resolved values, hence the re-declarations on [data-theme] elements). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
🖼️ Storybook Visual Comparison Report✅ No Storybook eyes differences detected! |
There was a problem hiding this comment.
Pull request overview
Adds a scoped “CodeAI next” (CADS) color-token schema behind data-brand='codeai-next' with a legacy↔CADS bridge, while preserving current legacy-brand rendering and introducing a separate codeai-audit all-pink auditing brand.
Changes:
- Introduces CADS canonical exports (
*_codeAi.css) plus generated/scopedcodeai-nexttokens and alias/shim layers to bridge legacy and CADS token schemas pre-cutover. - Adds a new
codeai-auditbrand (Ruby + frontend) and splits the MUI palette intoCodeaiTheme(CADS purple) vsCodeaiAuditTheme(hot pink). - Wires the new override layer into the style entry points and updates brand-specific logo/layout selectors and tests.
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| shared/css/user-menu.scss | Treat codeai-audit like CodeAI brands for responsive user-menu breakpoints. |
| lib/cdo/brand.rb | Adds codeai-audit brand code and config alongside existing brands. |
| frontend/packages/markdown/demo/main.tsx | Imports brandOverrides.css after colors.css for demo app. |
| frontend/packages/component-library/src/themes/README.md | Documents the new override layer, selectors, and MUI themes. |
| frontend/packages/component-library/src/themes/index.ts | Exports CodeaiAuditTheme. |
| frontend/packages/component-library/src/themes/codeai/index.ts | Updates CodeaiTheme palette to CADS purple ramp. |
| frontend/packages/component-library/src/themes/codeai-audit/index.ts | Adds hot-pink audit MUI theme. |
| frontend/packages/component-library-styles/scripts/generateBrandCodeAiNext.mjs | Generates scoped brandCodeAiNext.css from canonical CADS exports. |
| frontend/packages/component-library-styles/primitiveColors_codeAi.css | Adds canonical CADS primitive tokens (verbatim export). |
| frontend/packages/component-library-styles/colors.css | Removes old codeai-next pink audit block from legacy colors. |
| frontend/packages/component-library-styles/colors_codeAi.css | Adds canonical CADS semantic tokens (verbatim export). |
| frontend/packages/component-library-styles/brandOverrides.css | New aggregator importing shim/scoped/alias/audit layers. |
| frontend/packages/component-library-styles/brandLegacyShim.css | Maps CADS-only token names to legacy equivalents under legacy brands. |
| frontend/packages/component-library-styles/brandCodeAiNextAliases.css | Maps legacy token names onto CADS tokens under codeai-next. |
| frontend/packages/component-library-styles/brandCodeAiNext.css | Generated scoped CADS primitives + semantics under codeai-next. |
| frontend/packages/component-library-styles/brandCodeAiAudit.css | Moves the all-pink audit ramp to a dedicated codeai-audit brand. |
| frontend/apps/studio/src/routes/__root.tsx | Imports brandOverrides.css after colors.css. |
| dashboard/test/lib/brand_test.rb | Adds test coverage for codeai-audit brand resolution/config. |
| dashboard/app/assets/stylesheets/application.scss | Extends CodeAI logo layout rules to include codeai-audit. |
| apps/test/unit/util/brandTest.ts | Adds unit tests for codeai-audit brand + theme selection. |
| apps/src/util/createReactRoot.tsx | Imports brandOverrides.css alongside existing color imports. |
| apps/src/util/brand.ts | Adds codeai-audit brand code + maps to CodeaiAuditTheme. |
| apps/src/sites/studio/pages/code-studio.js | Imports brandOverrides.css after colors.css. |
Addresses a workflow-backed code review of the codeai-color-bridge PR: Storybook lost brand-switching when brand CSS moved out of colors.css, the pink audit brand missed ~34 CADS tokens that alias to raw legacy primitives, codeai-audit had no guard against becoming the sitewide default, the brandCodeAiNext.css generator could silently corrupt :root for every brand on a future re-export, and several docs/config had drifted out of sync (README, brand.rb comments, triplicated brand selector lists, triplicated MUI theme boilerplate, no freshness check on the generated CSS). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d680db5210
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The /frontend-studio route renders with layout: false, so the bare %html in frontend_studio/index.html.haml never got the data-brand attribute that application.html.haml sets. The entry point loads brandOverrides.css, but without the attribute none of the [data-brand='codeai-next'] / codeai-audit selectors can activate — ?brand= QA on that shell silently showed legacy colors. Found by Codex review on PR #73701. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The /frontend-studio route renders with layout: false, so the bare %html in frontend_studio/index.html.haml never got the data-brand attribute that application.html.haml sets. The entry point loads brandOverrides.css, but without the attribute none of the [data-brand='codeai-next'] / codeai-audit selectors can activate — ?brand= QA on that shell silently showed legacy colors. Found by Codex review on PR #73701. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The /frontend-studio route renders with layout: false, so the bare %html in frontend_studio/index.html.haml never got the data-brand attribute that application.html.haml sets. The entry point loads brandOverrides.css, but without the attribute none of the [data-brand='codeai-next'] / codeai-audit selectors can activate — ?brand= QA on that shell silently showed legacy colors. Found by Codex review on PR #73701. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…3721) * fix(rebrand): sync MUI theme with data-brand in frontend/ entry points frontend/apps/studio/src/routes/__root.tsx and frontend/packages/markdown/demo/main.tsx both load brandOverrides.css (codeai-color-bridge) but hardcoded CdoTheme, so MUI palette-driven components didn't rebrand under codeai-next/codeai-audit even though CSS tokens did. apps/src/util/brand.ts already solves this for the legacy apps/ workspace via getCurrentBrand()/getMuiThemeForBrand(), but frontend/ packages can't import from it, so this adds a getMuiThemeForBrand(brand) counterpart to component-library/themes (already a shared dependency of both) and wires both entry points to it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(rebrand): set data-brand on the frontend-studio Vite shell The /frontend-studio route renders with layout: false, so the bare %html in frontend_studio/index.html.haml never got the data-brand attribute that application.html.haml sets. The entry point loads brandOverrides.css, but without the attribute none of the [data-brand='codeai-next'] / codeai-audit selectors can activate — ?brand= QA on that shell silently showed legacy colors. Found by Codex review on PR #73701. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(rebrand): make the markdown demo brand-switchable via ?brand= param The previous guidance — set data-brand in devtools and reload — was self-defeating: the reload discards the attribute. Read ?brand= from the URL and stamp it on <html> before theme selection instead, mirroring the server-side brand router's param. Found by Copilot review on PR #73721. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Update dashboard/app/views/frontend_studio/index.html.haml Co-authored-by: Stephen Liang <stephenliang@users.noreply.github.com> * Update frontend/apps/studio/src/routes/__root.tsx Co-authored-by: Stephen Liang <stephenliang@users.noreply.github.com> * fix(rebrand): clean up duplicate JSDoc comment in __root.tsx Applying Stephen's review suggestion left a stray duplicate: GitHub applied it against the comment's original anchor position, which had shifted by one statement since the review ran, landing a "Root layout: ..." doc-comment above the `const theme = ...` line instead of cleanly replacing it. Down to one correctly-placed comment above function RootLayout(). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> Co-authored-by: Stephen Liang <stephenliang@users.noreply.github.com>
What
Ships the CADS (CodeAI Design System) color ramp behind
data-brand='codeai-next'without changing what legacy-brand users see, so the rebrand can be QA'd ahead of the cutover and enabled via thedefault-brandDCDO key (no deploy, instant rollback).The CADS exports change the token schema, not just values:
--borders-*→--border-*, the aqua/teal/purple brand families collapse into one brand family, ramp stepsextra-light/light→light/mid, anddisabled/selected/alphafamilies are new. Several primitive names (--brand-purple-50,--neutral-base-black, all grays/sentiments) exist in both schemas with different values, so the canonical files cannot load at:rootbefore cutover.How
New files in
frontend/packages/component-library-styles/:colors_codeAi.css,primitiveColors_codeAi.cssbrandCodeAiNext.css[data-brand='codeai-next']— generated byscripts/generateBrandCodeAiNext.mjs, rerun after design re-exportsbrandCodeAiNextAliases.cssbrandLegacyShim.cssbrandCodeAiAudit.csscolors.css(where it occupied codeai-next) to a newcodeai-auditbrandbrandOverrides.csscolors.cssby the four style entry pointsSupporting changes:
Cdo::Brand+apps/src/util/brand.ts: newcodeai-auditbrand code (?brand=codeai-auditpersists via the existing router). DSCO-coverage auditing moves there;?brand=codeai-nextnow shows real CADS colors.CodeaiThemegets the real CADS purple palette (#4C42CF/#928CEF/#3228B7); the hot-pink placeholder palette becomesCodeaiAuditTheme.dashboard/app/assets/stylesheets/application.scssandshared/css/user-menu.scssincludecodeai-audit.CSS mechanics worth knowing when reviewing:
:rootand[data-brand='x']tie at specificity (0,1,0); brand-scoped blocks carry:root/[data-theme]compounds to reach (0,2,0) and win independent of import order.var()chains on the element that declares them and inherit as resolved values, so the aliases/shim re-declare on[data-theme]-carrying elements — otherwise Lab2's nesteddata-theme='Dark'subtrees would inherit light-resolved values.Which schema is the base, and what gets deleted later
A common first read of this PR is "it converts the new tokens back to the old structure" — it's actually the opposite in the scope that matters, and both directions exist on purpose, one per brand scope:
codeai-next(the future default), the CADS schema is the base.brandCodeAiNext.cssdefines the new tokens natively;brandCodeAiNextAliases.cssmaps the old names onto them (--borders-brand-teal-primary: var(--border-brand-primary)). Old names are compatibility pointers into the new system, kept alive so unmigrated call sites are still rebranded on day one.brandLegacyShim.cssmaps the new names onto old values, only so code migrated early (or written fresh against CADS names) renders sensibly pre-cutover. This is the temporary half.Planned rework is deletion plus a mechanical rename, not a redesign:
brandCodeAiNextAliases.cssdoubles as the codemod table, with every design decision (teal→brand, extra-light/light→light/mid, strawberry→pink) already encoded one line per token.*_codeAi.cssfiles to:root, deletecolors.css,primitiveColors.css, the shim, the aliases, the aggregator, and the generator. Total disposable artifact: ~350 lines of alias/shim CSS plus a 70-line script. (The pink audit file overrides old names today; at cleanup it gets rewritten against CADS names.)Why not the inverse now (CADS at
:rootas the global base, legacy values mapped on top for pre-cutover): old→new is many-to-one (teal/purple/aqua primaries all map to the one brand family), so the shipped mapping is well-defined. The reverse is one-to-many — once a call site says--background-brand-primary, whether it "used to be" teal or purple is unrecoverable, so a legacy override would have to pick one and some surfaces would visibly change color before launch. It would also force the ~370-file rename immediately (conflicting with everything in flight) and turn rollback into a deploy instead of a DCDO flip. Same destination either way; this ordering puts the risky step after the deadline instead of before it.Mapping decisions needing design sign-off
extra-light/light→ CADSlight/mid;hover→mid; strawberry → pink;--background-neutral-lab→--background-neutral-primary(legacy dark lab value #121212 equals CADS dark primary exactly).--background-{sentiment}-lightcall sites move from a 20-level fill to a 5-level wash (the heavier step is now-mid; ~30 usages to revisit during call-site migration). CADS also defines light-mode--background-neutral-true-baseas black (1 usage).Examples:



Rollout
?brand=codeai-next, audit via?brand=codeai-audit.default-brandtocodeai-next.Cleanup checklist (post-cutover — so we don't forget)
The CADS token names already work everywhere (natively under
codeai-next, via the shim under legacy brands), so call sites can migrate any time — every migrated call site shrinks this list. Once both preconditions hold:--borders-,--background-brand-{teal,aqua,purple}-,--text-brand-{teal,aqua,purple}-,--accent-strawberry-,--text-neutral-inverse,--*-neutral-disabled,--background-neutral-lab, …) returns zero call sites,the teardown is a small deletion PR — no rewrites or re-mapping, since the mapping knowledge is baked into the migrated call sites by then:
brandCodeAiNextAliases.css(that file is the codemod table) — except ~30 usages of--background-{error,info,success,warning}-light, where the token kept its name but moved from a 20-level fill to a 5-level wash: each needs a human to choose-lightvs-midby intent.createReactRoot.tsx,code-studio.js, studio__root.tsx, markdown demo) atcolors_codeAi.css+primitiveColors_codeAi.css— they are already written in:rootform; that is why they were committed verbatim and the scoped copy is generated rather than hand-edited.colors.css,primitiveColors.css,brandLegacyShim.css,brandCodeAiNext.css,brandCodeAiNextAliases.css,brandOverrides.css, andscripts/generateBrandCodeAiNext.mjs.brandCodeAiAudit.cssto override the CADS token names (it pinks the legacy names today; the audit brand outlives the bridge).Cdo::Brand/brand.ts(fold the CADS ramp intocodeaior makecodeai-nextthe plain default; drop the MUI theme split if only one real brand remains).Testing
var()reference resolves within its scope; codeai-audit keeps full parity with the pink block it replaced.appstypecheck clean;brandTest.ts11/11 (new codeai-audit cases); eslint/stylelint/prettier/rubocop clean;brand_test.rbextended.?brand=codeai-next/?brand=codeai-auditand eyes baselines (default brand unchanged by construction, but please confirm on drone).🤖 Generated with Claude Code