[ZEPPELIN-6640] Theme the React remote from the host instead of the shell's CSS - #5420
Open
kimyenac wants to merge 1 commit into
Open
[ZEPPELIN-6640] Theme the React remote from the host instead of the shell's CSS#5420kimyenac wants to merge 1 commit into
kimyenac wants to merge 1 commit into
Conversation
…hell's CSS The remote wraps its tree in antd's ConfigProvider but never sets an algorithm, so it always builds light styles. Dark mode looks right only because the shell's global ng-zorro-antd rules target the same .ant-* class names, which leaves anything the shell cannot reach in light. The chart.js canvas keeps its 'apache#666' default text, about 3.2:1 against the dark page background, and its grid lines are invisible. Read the theme the shell already publishes on the document root, pick antd's dark or default algorithm from it, and set the two chart.js globals that ticks, legend labels and grid lines resolve from. No Angular change is needed.
voidmatcha
approved these changes
Aug 14, 2026
Member
There was a problem hiding this comment.
LGTM 👍
Nothing imports PublishedParagraph or TableVisualization in a spec, so reverting both files to their pre-PR state still leaves all 29 tests passing.
Adding resolve.alias to vitest.config.ts would make PublishedParagraph importable from a spec, and you could then assert that it renders with dark tokens under data-theme="dark". #5391 adds the same alias, but the content is identical so the conflict is trivial, and since there is no telling when that one gets reviewed and merged, applying it here first seems reasonable.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What is this PR for?
The React remote never learns which theme the shell is in.
PublishedParagraphwraps its tree in antd'sConfigProviderbut only setstoken.fontFamily, so antd always builds its styles from the default (light) algorithm.Dark mode still looks correct today, but not for a reason either side declares.
ThemeServicewritesdata-themeand adarkclass onto the document root, and the shell's global ng-zorro-antd stylesheet targets the same.ant-*class names the remote's markup happens to use, so the shell's dark rules land on top of the remote's own light CSS-in-JS. In the published paragraph with?react=truein dark mode,.ant-tablecomputes torgb(31, 31, 31). Disable every stylesheet except the remote's own injectedstyle[data-css-hash]tags and the same element becomesrgb(255, 255, 255)on the dark page.Anything the shell's CSS cannot reach stays light. The charts in
TableVisualizationare drawn on a canvas, and no chart config sets axis, grid or legend colors, so chart.js v4 defaults apply (#666text,rgba(0, 0, 0, 0.1)grid). Against the dark page background (#141414) the tick and category labels sit at about 3.2:1, below the 4.5:1 WCAG AA threshold for text, and the grid lines are effectively invisible.This gives the remote the theme as an input instead of letting it inherit one by accident.
src/theme/hostTheme.tsreads the theme the shell already publishes on the document root and follows it while mounted,ZeppelinThemeProviderselects antd's dark or default algorithm from it and exposes the resolved value through context for code that draws outside antd, andchartTheme.tssets the two chart.js globals that ticks, legend labels and grid lines resolve from.The theme is read from the DOM rather than passed in through
reactProps. The published paragraph still mounts through its ownwindow.reactApppath, so a props based version would have to be wired into that path as well as the directive, and the two host files it would touch are the ones ZEPPELIN-6564 and ZEPPELIN-6565 are currently changing. Reading the attribute the shell already publishes for its own CSS covers both mount paths and needs no host change, and a theme toggle then re-renders the remote without going through change detection. If you would rather keep host state flowing in through props, having the provider take an explicitthemeprop is a small follow-up.Matching the shell pixel for pixel is not the goal. antd's dark container token is
#141414where ng-zorro's is#1f1f1f, and where the shell's global rules still win, they win.What type of PR is it?
Bug Fix
Todos
None
What is the Jira issue?
https://issues.apache.org/jira/browse/ZEPPELIN-6640
How should this be tested?
projects/zeppelin-react/src/theme/: theme resolution from the document root and its fallbacks, live updates when the shell toggles the theme, antd algorithm selection asserted throughtheme.useToken(), and the chart.js defaults. The project's suite is green at 29 specs. Note that unit tests do not gate CI yet (ZEPPELIN-6566).?react=true, on a paragraph with a TABLE result. Switch to Bar Chart in dark mode: the axis labels, legend and grid lines are readable where they were not. The table view and light mode are unchanged.color: rgba(255, 255, 255, 0.85).npm run build).Screenshots (if appropriate)
before

after

Questions:
projects/zeppelin-react/README.mdgains the provider step in "Adding a new React module"