Rebrand: sync MUI theme with data-brand in frontend/ entry points#73721
Rebrand: sync MUI theme with data-brand in frontend/ entry points#73721levadadenys wants to merge 3 commits into
Conversation
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>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cdadee2d1c
ℹ️ 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>
There was a problem hiding this comment.
Pull request overview
Updates frontend/ entry points to select the correct MUI theme based on the active data-brand, keeping MUI palette-driven components consistent with the brand-specific CSS token overrides used for rebrand QA surfaces.
Changes:
- Add
getMuiThemeForBrand(brand: string | undefined)to@code-dot-org/component-library/themes, mappingdata-brandtoCdoTheme/CodeaiTheme/CodeaiAuditTheme. - Wire
frontend/apps/studioandfrontend/packages/markdowndemo entry points to usegetMuiThemeForBrand(document.documentElement.dataset.brand)instead of hardcodingCdoTheme. - Add unit tests and documentation for the new brand→theme selection API.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| frontend/packages/markdown/demo/main.tsx | Switch demo ThemeProvider to a brand-selected MUI theme. |
| frontend/packages/component-library/src/themes/README.md | Document how frontend/ entry points should select MUI theme from data-brand. |
| frontend/packages/component-library/src/themes/index.ts | Export the new getMuiThemeForBrand helper from the themes barrel. |
| frontend/packages/component-library/src/themes/getMuiThemeForBrand.ts | Implement brand string → MUI theme mapping. |
| frontend/packages/component-library/src/themes/tests/getMuiThemeForBrand.test.ts | Add unit tests covering supported brands and fallback behavior. |
| frontend/apps/studio/src/routes/__root.tsx | Switch studio root ThemeProvider to a brand-selected MUI theme. |
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>
| -# data-brand activates the brand-scoped design tokens loaded by this app's | ||
| -# entry (component-library-styles/brandOverrides.css); without it, | ||
| -# ?brand=codeai-next / codeai-audit QA silently falls back to legacy colors. | ||
| -# This shell renders with layout: false, so application.html.haml does not | ||
| -# set the attribute for us. |
There was a problem hiding this comment.
I think we can remove this comment, it's self documenting anyway.
| -# data-brand activates the brand-scoped design tokens loaded by this app's | |
| -# entry (component-library-styles/brandOverrides.css); without it, | |
| -# ?brand=codeai-next / codeai-audit QA silently falls back to legacy colors. | |
| -# This shell renders with layout: false, so application.html.haml does not | |
| -# set the attribute for us. |
| // data-brand is set server-side via Cdo::Brand before this bundle loads, and | ||
| // doesn't change without a full page reload, so it's safe to read once here | ||
| // rather than re-resolving per render. |
There was a problem hiding this comment.
Same, we can keep the comments clean, no need to change from before.
| // data-brand is set server-side via Cdo::Brand before this bundle loads, and | |
| // doesn't change without a full page reload, so it's safe to read once here | |
| // rather than re-resolving per render. | |
| /** Root layout: applies the CDO MUI theme and Bootstrap providers to all routes. */ |
|
|
||
| `CodeaiTheme` and `CodeaiAuditTheme` inherit all typography and component style overrides from `CdoTheme` via `createTheme(CdoTheme, { palette: ... })`. Only the palette differs. | ||
|
|
||
| Entry points under `frontend/` (which cannot import `apps/src/util/brand.ts`) select the MUI theme with `getMuiThemeForBrand(document.documentElement.dataset.brand)`, exported from this package. Every entry point that loads `brandOverrides.css` should also call this, so CSS tokens and MUI palette-driven components stay in sync under the same brand — see `frontend/apps/studio/src/routes/__root.tsx` and `frontend/packages/markdown/demo/main.tsx`. |
There was a problem hiding this comment.
Let me add a core package utility that represents what "brand" we're on. #73721 - this will be a followup and non-blocking.
| export {default as CdoTheme} from './code.org'; | ||
| export {default as CodeaiTheme} from './codeai'; | ||
| export {default as CodeaiAuditTheme} from './codeai-audit'; |
There was a problem hiding this comment.
Do we want to prevent individual usages of specific themes and route all requests to getMuiThemeForBrand? If so, we can remove the exports or add an eslint rule for restricted imports.
What
Follow-up to #73701, closing two findings from its Copilot re-review:
frontend/apps/studio/src/routes/__root.tsxandfrontend/packages/markdown/demo/main.tsxboth loadbrandOverrides.css, so their CSS tokens correctly flip under?brand=codeai-next/codeai-audit, but both hardcoded<ThemeProvider theme={CdoTheme}>— so MUI palette-driven components (buttons, etc.) stayed Code.org-purple regardless of the active brand, giving an inconsistent preview for exactly the two surfaces meant to QA the rebrand.Stacked on #73701 — this branch is based on
denys/re/codeai-color-bridge, notstaging, since it depends onbrandOverrides.css,CodeaiTheme, andCodeaiAuditThemeintroduced there. Merge #73701 first.How
apps/src/util/brand.tsalready solves this for the legacyapps/webpack workspace (getCurrentBrand()/getMuiThemeForBrand()), already used correctly bycreateReactRoot.tsxandcode-studio.js. Butfrontend/packages can't import fromapps/src/(separate Turborepo workspace, separate build tooling), and there was no brand-detection code anywhere underfrontend/.Added a
getMuiThemeForBrand(brand: string | undefined)export tofrontend/packages/component-library/src/themes— already a shared dependency of bothapps/andfrontend/for the theme objects themselves. It takes the rawdata-brandattribute value directly (not theBrandCodeunion type, which frontend/ has no equivalent of) and maps it toCdoTheme/CodeaiTheme/CodeaiAuditTheme.Wired both entry points to call it with
document.documentElement.dataset.brand, computed once (brand doesn't change without a full page reload — matches the existing pattern increateReactRoot.tsx).Testing
getMuiThemeForBrand(6 cases: both real brands,code/codeai/unknown/undefined all fall back toCdoTheme).component-librarytypecheck + full test suite (348 tests) pass.studioandmarkdownpackages typecheck and build clean with the new import wired in.git stashthat the one remaining typecheck error instudio(@code-dot-org/music-lab/mocks) is pre-existing and unrelated to this change.🤖 Generated with Claude Code