Skip to content

Rebrand: CADS color tokens under codeai-next, legacy-token bridge, codeai-audit pink brand#73701

Merged
levadadenys merged 2 commits into
stagingfrom
denys/re/codeai-color-bridge
Jul 16, 2026
Merged

Rebrand: CADS color tokens under codeai-next, legacy-token bridge, codeai-audit pink brand#73701
levadadenys merged 2 commits into
stagingfrom
denys/re/codeai-color-bridge

Conversation

@levadadenys

@levadadenys levadadenys commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

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 the default-brand DCDO 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 steps extra-light/lightlight/mid, and disabled/selected/alpha families 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 :root before cutover.

How

New files in frontend/packages/component-library-styles/:

File Role
colors_codeAi.css, primitiveColors_codeAi.css Canonical CADS exports, verbatim; not imported directly pre-cutover
brandCodeAiNext.css Canonical files rescoped under [data-brand='codeai-next']generated by scripts/generateBrandCodeAiNext.mjs, rerun after design re-exports
brandCodeAiNextAliases.css Every legacy token name mapped onto its CADS successor in that scope, so unmigrated call sites are rebranded too
brandLegacyShim.css CADS-only token names defined under legacy brands, so call sites can migrate to CADS names before cutover
brandCodeAiAudit.css The all-pink audit ramp, moved out of colors.css (where it occupied codeai-next) to a new codeai-audit brand
brandOverrides.css Aggregator; imported after colors.css by the four style entry points

Supporting changes:

  • Cdo::Brand + apps/src/util/brand.ts: new codeai-audit brand code (?brand=codeai-audit persists via the existing router). DSCO-coverage auditing moves there; ?brand=codeai-next now shows real CADS colors.
  • MUI: CodeaiTheme gets the real CADS purple palette (#4C42CF/#928CEF/#3228B7); the hot-pink placeholder palette becomes CodeaiAuditTheme.
  • Logo-layout selectors in dashboard/app/assets/stylesheets/application.scss and shared/css/user-menu.scss include codeai-audit.

CSS mechanics worth knowing when reviewing:

  • :root and [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.
  • Custom properties substitute 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 nested data-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:

  • Under codeai-next (the future default), the CADS schema is the base. brandCodeAiNext.css defines the new tokens natively; brandCodeAiNextAliases.css maps 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.
  • Under the legacy brands (until cutover), the old schema is the base. brandLegacyShim.css maps 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:

  1. Call-site migration (~2,800 usages of legacy names): required in every possible approach; the bridge just detaches it from the launch date. By then it is a dumb find-and-replace — brandCodeAiNextAliases.css doubles as the codemod table, with every design decision (teal→brand, extra-light/light→light/mid, strawberry→pink) already encoded one line per token.
  2. Cleanup: promote the two canonical *_codeAi.css files to :root, delete colors.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 :root as 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

  • Legacy aqua/teal/purple brand tokens all collapse onto the CADS brand family (pre-cutover teal and purple surfaces converge on CADS purple).
  • Legacy background extra-light/light → CADS light/mid; hovermid; strawberry → pink; --background-neutral-lab--background-neutral-primary (legacy dark lab value #121212 equals CADS dark primary exactly).
  • Same-name tokens whose meaning shifted cannot be aliased and follow the CADS definition: legacy --background-{sentiment}-light call 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-base as black (1 usage).

Examples:
image
image
image

Rollout

  1. Merge: no visible change for legacy brands. QA via ?brand=codeai-next, audit via ?brand=codeai-audit.
  2. Cutover: flip DCDO default-brand to codeai-next.
  3. Cleanup: see checklist below.

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:

  • the cutover has happened (default brand is on the CADS ramp), and
  • a grep for legacy token names (--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:

  • Migrate call sites legacy→CADS names. Mechanical 1:1 rename for everything in 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 -light vs -mid by intent.
  • Add a stylelint rule banning legacy token names so the count only goes down (this can and should land before cutover, as soon as teams start migrating).
  • Point the four style entry points (createReactRoot.tsx, code-studio.js, studio __root.tsx, markdown demo) at colors_codeAi.css + primitiveColors_codeAi.css — they are already written in :root form; that is why they were committed verbatim and the scoped copy is generated rather than hand-edited.
  • Delete colors.css, primitiveColors.css, brandLegacyShim.css, brandCodeAiNext.css, brandCodeAiNextAliases.css, brandOverrides.css, and scripts/generateBrandCodeAiNext.mjs.
  • Rewrite brandCodeAiAudit.css to override the CADS token names (it pinks the legacy names today; the audit brand outlives the bridge).
  • Consolidate brand codes in Cdo::Brand / brand.ts (fold the CADS ramp into codeai or make codeai-next the plain default; drop the MUI theme split if only one real brand remains).

Testing

  • Scripted coverage checks: all 107 legacy semantic + 129 legacy primitive tokens resolve under codeai-next; all 141 CADS tokens resolve under legacy brands; every var() reference resolves within its scope; codeai-audit keeps full parity with the pink block it replaced.
  • Cascade simulation (models html + nested dark div per brand): 17 spot checks pass, incl. dark-subtree re-resolution and the alpha flip to white-alpha in dark.
  • apps typecheck clean; brandTest.ts 11/11 (new codeai-audit cases); eslint/stylelint/prettier/rubocop clean; brand_test.rb extended.
  • Not covered locally: real-browser pass over ?brand=codeai-next/?brand=codeai-audit and eyes baselines (default brand unchanged by construction, but please confirm on drone).

🤖 Generated with Claude Code

…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>
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

🖼️ Storybook Visual Comparison Report

✅ No Storybook eyes differences detected!

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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/scoped codeai-next tokens and alias/shim layers to bridge legacy and CADS token schemas pre-cutover.
  • Adds a new codeai-audit brand (Ruby + frontend) and splits the MUI palette into CodeaiTheme (CADS purple) vs CodeaiAuditTheme (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.

Comment thread lib/cdo/brand.rb Outdated
Comment thread frontend/packages/component-library/src/themes/README.md
Comment thread frontend/packages/component-library/src/themes/README.md
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>
@levadadenys
levadadenys requested review from Copilot and removed request for Copilot July 8, 2026 14:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 28 out of 28 changed files in this pull request and generated 4 comments.

Comment thread lib/cdo/brand.rb Outdated
Comment thread frontend/packages/component-library/src/themes/README.md
Comment thread frontend/apps/studio/src/routes/__root.tsx
Comment thread frontend/packages/markdown/demo/main.tsx
@levadadenys
levadadenys marked this pull request as ready for review July 8, 2026 15:47
@levadadenys
levadadenys requested a review from a team as a code owner July 8, 2026 15:47

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Comment thread frontend/apps/studio/src/routes/__root.tsx
levadadenys added a commit that referenced this pull request Jul 9, 2026
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>
@levadadenys
levadadenys requested review from a team and etaderhold and removed request for a team July 9, 2026 15:04
@levadadenys
levadadenys merged commit adc5ec9 into staging Jul 16, 2026
19 checks passed
@levadadenys
levadadenys deleted the denys/re/codeai-color-bridge branch July 16, 2026 03:51
levadadenys added a commit that referenced this pull request Jul 16, 2026
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>
levadadenys added a commit that referenced this pull request Jul 16, 2026
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>
levadadenys added a commit that referenced this pull request Jul 17, 2026
…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>
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.

3 participants