Skip to content

UI: Rework Monaco editor theme to match Chakra UI palette - #64748

Merged
pierrejeambrun merged 5 commits into
apache:mainfrom
shivaam:fix/monaco-theme-64253
Apr 14, 2026
Merged

UI: Rework Monaco editor theme to match Chakra UI palette#64748
pierrejeambrun merged 5 commits into
apache:mainfrom
shivaam:fix/monaco-theme-64253

Conversation

@shivaam

@shivaamshivaam commented Apr 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Register custom airflow-light / airflow-dark Monaco themes derived from Chakra UI color tokens so that every Monaco editor in the UI (DAG Code viewer, code diff viewer, JSON editor, RenderedJsonField) visually integrates with the rest of the app instead of using Monaco's default vs / vs-dark themes.

closes: #64253

Open Questions

  1. Design question: I added a module-level themesRegistered flag so defineTheme
    only runs on the first beforeMount. Without it, pages with many editors (e.g.
    XCom table with ~50 rows) re-register themes on every mount. Measured cost without the guard: ~4ms on a 50-editor page. Negligible. Happy to drop the flag for simpler code + tests if you prefer..
  2. Design question: Chakra v3 uses OKLCH, Monaco's defineTheme only accepts
    #rrggbb. I convert by rasterizing a 1x1 canvas pixel and reading back sRGB
    via getImageData. I checked ctx.fillStyle readback — it preserves the OKLCH string unchanged on Chrome 111+, so that path silently fails (this is what PR Rework Monaco editor style to match Chakra UI color palette  #64268 does).

Implementation notes

  • New hook useMonacoTheme (src/context/colorMode/useMonacoTheme.ts) — registers both custom themes exactly once via a module-level flag, returns a stable beforeMount callback and the correct theme name for the current color mode.
  • inherit: true + empty rules — Monaco's default syntax highlighting (keywords, strings, comments) is preserved. Only editor shell colors (background, foreground, gutter, selection, scrollbar, line numbers) are overridden.
  • OKLCH → hex conversion via getImageData — Chakra v3 uses OKLCH colors. ctx.fillStyle readback cannot be relied on because Chrome 111+ preserves the OKLCH string instead of converting to hex, which Monaco would silently ignore.
  • Single registration — themes are registered once per session via a module-level flag so pages with many editor instances (e.g. XCom table with many RenderedJsonField rows) don't pay the cost on every mount.
  • All four Monaco usages (JsonEditor, RenderedJsonField, Code, CodeDiffViewer) are updated to use the hook. No changes to component structure, dynamic height behavior, or any other behavior beyond theme wiring.

How to test

  1. breeze start-airflow --dev-mode --load-example-dags
  2. Visit the DAG Code tab, XCom page, Connections > Edit > Extra field, Trigger DAG dialog, DAG Details page
  3. Toggle between light and dark mode — editor shell colors should smoothly match the surrounding Chakra UI surfaces instead of the default VS Code palette
white_color_dag_codedag_rundag_code_diffScreenshot 2026-04-05 at 12 16 12 PMaudit_logScreenshot 2026-04-05 at 12 21 04 PMxcom
Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 4.6)

Generated-by: Claude Code (Opus 4.6) following the guidelines

@boring-cyborgboring-cyborgBot added the area:UI Related to UI/UX. For Frontend Developers. label Apr 5, 2026
@shivaamshivaam mentioned this pull request Apr 5, 2026
1 task

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just one nit, but directions looks good to me.

Let me know when this is out of draft (fix static checks, CI more generally) and it's ready for a more in depth review + local testing.

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.ts Outdated
@shivaam

Copy link
Copy Markdown
ContributorAuthor

Just one nit, but directions looks good to me.

Let me know when this is out of draft (fix static checks, CI more generally) and it's ready for a more in depth review + local testing.

@pierrejeambrun handled the nits and the PR is ready for local testing

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. Tested locally and working as expected.

IT's also nicely inheriting custom theming:
Overriding the brand color palette (see text selection)
Image

Someone overriding the 'grey' color palette will have something like:

Image

vs

Image

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.ts Outdated
@kaxil
kaxil requested a review from CopilotApril 10, 2026 19:55

CopilotAI 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

Registers custom airflow-light / airflow-dark Monaco themes derived from Chakra UI tokens, and wires them into all Monaco editor usages so editor chrome matches the app’s design system.

Changes:

  • Add useMonacoTheme hook that defines and selects the Monaco theme based on current Chakra color mode.
  • Update all Monaco editor call sites (Editor + DiffEditor) to use the hook’s beforeMount + theme.
  • Add unit tests covering theme selection and one-time registration behavior.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
airflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.tsDefines custom Monaco themes using Chakra CSS variables and exposes beforeMount + theme.
airflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.test.tsTests theme name selection and single registration behavior.
airflow-core/src/airflow/ui/src/context/colorMode/index.tsExports useMonacoTheme from the colorMode barrel.
airflow-core/src/airflow/ui/src/pages/Dag/Code/Code.tsxUses useMonacoTheme for the DAG code viewer Monaco editor.
airflow-core/src/airflow/ui/src/pages/Dag/Code/CodeDiffViewer.tsxUses useMonacoTheme for the DAG code diff Monaco editor.
airflow-core/src/airflow/ui/src/components/JsonEditor.tsxUses useMonacoTheme for the JSON editor component.
airflow-core/src/airflow/ui/src/components/RenderedJsonField.tsxUses useMonacoTheme for read-only rendered JSON Monaco editor instances.

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.test.ts Outdated
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: apache#64253
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
@shivaam
shivaamforce-pushed the fix/monaco-theme-64253 branch from 061ca08 to 7dba46aCompareApril 11, 2026 13:21
@shivaam

Copy link
Copy Markdown
ContributorAuthor

Pushed 7dba46a addressing review feedback:

Canvas → culori for color conversion (@pierrejeambrun)
afterEach(vi.restoreAllMocks()) to prevent mock leak (@Copilot)

pierrejeambrun
pierrejeambrun previously approved these changes Apr 14, 2026

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

My bad, my testing setup was wrong. Working as expected thanks 🎉 , nice one

@pierrejeambrun
pierrejeambrun merged commit bfe46f6 into apache:mainApr 14, 2026
80 checks passed
github-actionsBot pushed a commit that referenced this pull request Apr 14, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

Backport successfully created: v3-2-test

Note: As of Merging PRs targeted for Airflow 3.X
the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.

In matter of doubt please ask in #release-management Slack channel.

StatusBranchResult
v3-2-testPR Link

@jscheffl

Copy link
Copy Markdown
Contributor

Cool! Thanks for this UX improvement!

@shivaam

Copy link
Copy Markdown
ContributorAuthor

Cool! Thanks for this UX improvement!

You are welcome. Happy to contribute:)

vatsrahul1001 pushed a commit that referenced this pull request Apr 23, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
potiuk pushed a commit that referenced this pull request Apr 26, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
potiuk added a commit that referenced this pull request Apr 26, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:UIRelated to UI/UX. For Frontend Developers.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rework style for the monaco-editor

5 participants

@shivaam@jscheffl@pierrejeambrun@vatsrahul1001
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
UI: Rework Monaco editor theme to match Chakra UI palette by shivaam · Pull Request #64748 · apache/airflow · GitHub
Skip to content

UI: Rework Monaco editor theme to match Chakra UI palette - #64748

Merged
pierrejeambrun merged 5 commits into
apache:mainfrom
shivaam:fix/monaco-theme-64253
Apr 14, 2026
Merged

UI: Rework Monaco editor theme to match Chakra UI palette#64748
pierrejeambrun merged 5 commits into
apache:mainfrom
shivaam:fix/monaco-theme-64253

Conversation

@shivaam

@shivaamshivaam commented Apr 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Register custom airflow-light / airflow-dark Monaco themes derived from Chakra UI color tokens so that every Monaco editor in the UI (DAG Code viewer, code diff viewer, JSON editor, RenderedJsonField) visually integrates with the rest of the app instead of using Monaco's default vs / vs-dark themes.

closes: #64253

Open Questions

  1. Design question: I added a module-level themesRegistered flag so defineTheme
    only runs on the first beforeMount. Without it, pages with many editors (e.g.
    XCom table with ~50 rows) re-register themes on every mount. Measured cost without the guard: ~4ms on a 50-editor page. Negligible. Happy to drop the flag for simpler code + tests if you prefer..
  2. Design question: Chakra v3 uses OKLCH, Monaco's defineTheme only accepts
    #rrggbb. I convert by rasterizing a 1x1 canvas pixel and reading back sRGB
    via getImageData. I checked ctx.fillStyle readback — it preserves the OKLCH string unchanged on Chrome 111+, so that path silently fails (this is what PR Rework Monaco editor style to match Chakra UI color palette  #64268 does).

Implementation notes

  • New hook useMonacoTheme (src/context/colorMode/useMonacoTheme.ts) — registers both custom themes exactly once via a module-level flag, returns a stable beforeMount callback and the correct theme name for the current color mode.
  • inherit: true + empty rules — Monaco's default syntax highlighting (keywords, strings, comments) is preserved. Only editor shell colors (background, foreground, gutter, selection, scrollbar, line numbers) are overridden.
  • OKLCH → hex conversion via getImageData — Chakra v3 uses OKLCH colors. ctx.fillStyle readback cannot be relied on because Chrome 111+ preserves the OKLCH string instead of converting to hex, which Monaco would silently ignore.
  • Single registration — themes are registered once per session via a module-level flag so pages with many editor instances (e.g. XCom table with many RenderedJsonField rows) don't pay the cost on every mount.
  • All four Monaco usages (JsonEditor, RenderedJsonField, Code, CodeDiffViewer) are updated to use the hook. No changes to component structure, dynamic height behavior, or any other behavior beyond theme wiring.

How to test

  1. breeze start-airflow --dev-mode --load-example-dags
  2. Visit the DAG Code tab, XCom page, Connections > Edit > Extra field, Trigger DAG dialog, DAG Details page
  3. Toggle between light and dark mode — editor shell colors should smoothly match the surrounding Chakra UI surfaces instead of the default VS Code palette
white_color_dag_codedag_rundag_code_diffScreenshot 2026-04-05 at 12 16 12 PMaudit_logScreenshot 2026-04-05 at 12 21 04 PMxcom
Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 4.6)

Generated-by: Claude Code (Opus 4.6) following the guidelines

@boring-cyborgboring-cyborgBot added the area:UI Related to UI/UX. For Frontend Developers. label Apr 5, 2026
@shivaamshivaam mentioned this pull request Apr 5, 2026
1 task

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just one nit, but directions looks good to me.

Let me know when this is out of draft (fix static checks, CI more generally) and it's ready for a more in depth review + local testing.

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.ts Outdated
@shivaam

Copy link
Copy Markdown
ContributorAuthor

Just one nit, but directions looks good to me.

Let me know when this is out of draft (fix static checks, CI more generally) and it's ready for a more in depth review + local testing.

@pierrejeambrun handled the nits and the PR is ready for local testing

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. Tested locally and working as expected.

IT's also nicely inheriting custom theming:
Overriding the brand color palette (see text selection)
Image

Someone overriding the 'grey' color palette will have something like:

Image

vs

Image

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.ts Outdated
@kaxil
kaxil requested a review from CopilotApril 10, 2026 19:55

CopilotAI 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

Registers custom airflow-light / airflow-dark Monaco themes derived from Chakra UI tokens, and wires them into all Monaco editor usages so editor chrome matches the app’s design system.

Changes:

  • Add useMonacoTheme hook that defines and selects the Monaco theme based on current Chakra color mode.
  • Update all Monaco editor call sites (Editor + DiffEditor) to use the hook’s beforeMount + theme.
  • Add unit tests covering theme selection and one-time registration behavior.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
airflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.tsDefines custom Monaco themes using Chakra CSS variables and exposes beforeMount + theme.
airflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.test.tsTests theme name selection and single registration behavior.
airflow-core/src/airflow/ui/src/context/colorMode/index.tsExports useMonacoTheme from the colorMode barrel.
airflow-core/src/airflow/ui/src/pages/Dag/Code/Code.tsxUses useMonacoTheme for the DAG code viewer Monaco editor.
airflow-core/src/airflow/ui/src/pages/Dag/Code/CodeDiffViewer.tsxUses useMonacoTheme for the DAG code diff Monaco editor.
airflow-core/src/airflow/ui/src/components/JsonEditor.tsxUses useMonacoTheme for the JSON editor component.
airflow-core/src/airflow/ui/src/components/RenderedJsonField.tsxUses useMonacoTheme for read-only rendered JSON Monaco editor instances.

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.test.ts Outdated
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: apache#64253
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
@shivaam
shivaamforce-pushed the fix/monaco-theme-64253 branch from 061ca08 to 7dba46aCompareApril 11, 2026 13:21
@shivaam

Copy link
Copy Markdown
ContributorAuthor

Pushed 7dba46a addressing review feedback:

Canvas → culori for color conversion (@pierrejeambrun)
afterEach(vi.restoreAllMocks()) to prevent mock leak (@Copilot)

pierrejeambrun
pierrejeambrun previously approved these changes Apr 14, 2026

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

My bad, my testing setup was wrong. Working as expected thanks 🎉 , nice one

@pierrejeambrun
pierrejeambrun merged commit bfe46f6 into apache:mainApr 14, 2026
80 checks passed
github-actionsBot pushed a commit that referenced this pull request Apr 14, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

Backport successfully created: v3-2-test

Note: As of Merging PRs targeted for Airflow 3.X
the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.

In matter of doubt please ask in #release-management Slack channel.

StatusBranchResult
v3-2-testPR Link

@jscheffl

Copy link
Copy Markdown
Contributor

Cool! Thanks for this UX improvement!

@shivaam

Copy link
Copy Markdown
ContributorAuthor

Cool! Thanks for this UX improvement!

You are welcome. Happy to contribute:)

vatsrahul1001 pushed a commit that referenced this pull request Apr 23, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
potiuk pushed a commit that referenced this pull request Apr 26, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
potiuk added a commit that referenced this pull request Apr 26, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:UIRelated to UI/UX. For Frontend Developers.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rework style for the monaco-editor

5 participants

@shivaam@jscheffl@pierrejeambrun@vatsrahul1001
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' UI: Rework Monaco editor theme to match Chakra UI palette by shivaam · Pull Request #64748 · apache/airflow · GitHub
Skip to content

UI: Rework Monaco editor theme to match Chakra UI palette - #64748

Merged
pierrejeambrun merged 5 commits into
apache:mainfrom
shivaam:fix/monaco-theme-64253
Apr 14, 2026
Merged

UI: Rework Monaco editor theme to match Chakra UI palette#64748
pierrejeambrun merged 5 commits into
apache:mainfrom
shivaam:fix/monaco-theme-64253

Conversation

@shivaam

@shivaamshivaam commented Apr 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Register custom airflow-light / airflow-dark Monaco themes derived from Chakra UI color tokens so that every Monaco editor in the UI (DAG Code viewer, code diff viewer, JSON editor, RenderedJsonField) visually integrates with the rest of the app instead of using Monaco's default vs / vs-dark themes.

closes: #64253

Open Questions

  1. Design question: I added a module-level themesRegistered flag so defineTheme
    only runs on the first beforeMount. Without it, pages with many editors (e.g.
    XCom table with ~50 rows) re-register themes on every mount. Measured cost without the guard: ~4ms on a 50-editor page. Negligible. Happy to drop the flag for simpler code + tests if you prefer..
  2. Design question: Chakra v3 uses OKLCH, Monaco's defineTheme only accepts
    #rrggbb. I convert by rasterizing a 1x1 canvas pixel and reading back sRGB
    via getImageData. I checked ctx.fillStyle readback — it preserves the OKLCH string unchanged on Chrome 111+, so that path silently fails (this is what PR Rework Monaco editor style to match Chakra UI color palette  #64268 does).

Implementation notes

  • New hook useMonacoTheme (src/context/colorMode/useMonacoTheme.ts) — registers both custom themes exactly once via a module-level flag, returns a stable beforeMount callback and the correct theme name for the current color mode.
  • inherit: true + empty rules — Monaco's default syntax highlighting (keywords, strings, comments) is preserved. Only editor shell colors (background, foreground, gutter, selection, scrollbar, line numbers) are overridden.
  • OKLCH → hex conversion via getImageData — Chakra v3 uses OKLCH colors. ctx.fillStyle readback cannot be relied on because Chrome 111+ preserves the OKLCH string instead of converting to hex, which Monaco would silently ignore.
  • Single registration — themes are registered once per session via a module-level flag so pages with many editor instances (e.g. XCom table with many RenderedJsonField rows) don't pay the cost on every mount.
  • All four Monaco usages (JsonEditor, RenderedJsonField, Code, CodeDiffViewer) are updated to use the hook. No changes to component structure, dynamic height behavior, or any other behavior beyond theme wiring.

How to test

  1. breeze start-airflow --dev-mode --load-example-dags
  2. Visit the DAG Code tab, XCom page, Connections > Edit > Extra field, Trigger DAG dialog, DAG Details page
  3. Toggle between light and dark mode — editor shell colors should smoothly match the surrounding Chakra UI surfaces instead of the default VS Code palette
white_color_dag_codedag_rundag_code_diffScreenshot 2026-04-05 at 12 16 12 PMaudit_logScreenshot 2026-04-05 at 12 21 04 PMxcom
Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 4.6)

Generated-by: Claude Code (Opus 4.6) following the guidelines

@boring-cyborgboring-cyborgBot added the area:UI Related to UI/UX. For Frontend Developers. label Apr 5, 2026
@shivaamshivaam mentioned this pull request Apr 5, 2026
1 task

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just one nit, but directions looks good to me.

Let me know when this is out of draft (fix static checks, CI more generally) and it's ready for a more in depth review + local testing.

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.ts Outdated
@shivaam

Copy link
Copy Markdown
ContributorAuthor

Just one nit, but directions looks good to me.

Let me know when this is out of draft (fix static checks, CI more generally) and it's ready for a more in depth review + local testing.

@pierrejeambrun handled the nits and the PR is ready for local testing

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. Tested locally and working as expected.

IT's also nicely inheriting custom theming:
Overriding the brand color palette (see text selection)
Image

Someone overriding the 'grey' color palette will have something like:

Image

vs

Image

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.ts Outdated
@kaxil
kaxil requested a review from CopilotApril 10, 2026 19:55

CopilotAI 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

Registers custom airflow-light / airflow-dark Monaco themes derived from Chakra UI tokens, and wires them into all Monaco editor usages so editor chrome matches the app’s design system.

Changes:

  • Add useMonacoTheme hook that defines and selects the Monaco theme based on current Chakra color mode.
  • Update all Monaco editor call sites (Editor + DiffEditor) to use the hook’s beforeMount + theme.
  • Add unit tests covering theme selection and one-time registration behavior.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
airflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.tsDefines custom Monaco themes using Chakra CSS variables and exposes beforeMount + theme.
airflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.test.tsTests theme name selection and single registration behavior.
airflow-core/src/airflow/ui/src/context/colorMode/index.tsExports useMonacoTheme from the colorMode barrel.
airflow-core/src/airflow/ui/src/pages/Dag/Code/Code.tsxUses useMonacoTheme for the DAG code viewer Monaco editor.
airflow-core/src/airflow/ui/src/pages/Dag/Code/CodeDiffViewer.tsxUses useMonacoTheme for the DAG code diff Monaco editor.
airflow-core/src/airflow/ui/src/components/JsonEditor.tsxUses useMonacoTheme for the JSON editor component.
airflow-core/src/airflow/ui/src/components/RenderedJsonField.tsxUses useMonacoTheme for read-only rendered JSON Monaco editor instances.

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.test.ts Outdated
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: apache#64253
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
@shivaam
shivaamforce-pushed the fix/monaco-theme-64253 branch from 061ca08 to 7dba46aCompareApril 11, 2026 13:21
@shivaam

Copy link
Copy Markdown
ContributorAuthor

Pushed 7dba46a addressing review feedback:

Canvas → culori for color conversion (@pierrejeambrun)
afterEach(vi.restoreAllMocks()) to prevent mock leak (@Copilot)

pierrejeambrun
pierrejeambrun previously approved these changes Apr 14, 2026

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

My bad, my testing setup was wrong. Working as expected thanks 🎉 , nice one

@pierrejeambrun
pierrejeambrun merged commit bfe46f6 into apache:mainApr 14, 2026
80 checks passed
github-actionsBot pushed a commit that referenced this pull request Apr 14, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

Backport successfully created: v3-2-test

Note: As of Merging PRs targeted for Airflow 3.X
the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.

In matter of doubt please ask in #release-management Slack channel.

StatusBranchResult
v3-2-testPR Link

@jscheffl

Copy link
Copy Markdown
Contributor

Cool! Thanks for this UX improvement!

@shivaam

Copy link
Copy Markdown
ContributorAuthor

Cool! Thanks for this UX improvement!

You are welcome. Happy to contribute:)

vatsrahul1001 pushed a commit that referenced this pull request Apr 23, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
potiuk pushed a commit that referenced this pull request Apr 26, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
potiuk added a commit that referenced this pull request Apr 26, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:UIRelated to UI/UX. For Frontend Developers.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rework style for the monaco-editor

5 participants

@shivaam@jscheffl@pierrejeambrun@vatsrahul1001
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' UI: Rework Monaco editor theme to match Chakra UI palette by shivaam · Pull Request #64748 · apache/airflow · GitHub
Skip to content

UI: Rework Monaco editor theme to match Chakra UI palette - #64748

Merged
pierrejeambrun merged 5 commits into
apache:mainfrom
shivaam:fix/monaco-theme-64253
Apr 14, 2026
Merged

UI: Rework Monaco editor theme to match Chakra UI palette#64748
pierrejeambrun merged 5 commits into
apache:mainfrom
shivaam:fix/monaco-theme-64253

Conversation

@shivaam

@shivaamshivaam commented Apr 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Register custom airflow-light / airflow-dark Monaco themes derived from Chakra UI color tokens so that every Monaco editor in the UI (DAG Code viewer, code diff viewer, JSON editor, RenderedJsonField) visually integrates with the rest of the app instead of using Monaco's default vs / vs-dark themes.

closes: #64253

Open Questions

  1. Design question: I added a module-level themesRegistered flag so defineTheme
    only runs on the first beforeMount. Without it, pages with many editors (e.g.
    XCom table with ~50 rows) re-register themes on every mount. Measured cost without the guard: ~4ms on a 50-editor page. Negligible. Happy to drop the flag for simpler code + tests if you prefer..
  2. Design question: Chakra v3 uses OKLCH, Monaco's defineTheme only accepts
    #rrggbb. I convert by rasterizing a 1x1 canvas pixel and reading back sRGB
    via getImageData. I checked ctx.fillStyle readback — it preserves the OKLCH string unchanged on Chrome 111+, so that path silently fails (this is what PR Rework Monaco editor style to match Chakra UI color palette  #64268 does).

Implementation notes

  • New hook useMonacoTheme (src/context/colorMode/useMonacoTheme.ts) — registers both custom themes exactly once via a module-level flag, returns a stable beforeMount callback and the correct theme name for the current color mode.
  • inherit: true + empty rules — Monaco's default syntax highlighting (keywords, strings, comments) is preserved. Only editor shell colors (background, foreground, gutter, selection, scrollbar, line numbers) are overridden.
  • OKLCH → hex conversion via getImageData — Chakra v3 uses OKLCH colors. ctx.fillStyle readback cannot be relied on because Chrome 111+ preserves the OKLCH string instead of converting to hex, which Monaco would silently ignore.
  • Single registration — themes are registered once per session via a module-level flag so pages with many editor instances (e.g. XCom table with many RenderedJsonField rows) don't pay the cost on every mount.
  • All four Monaco usages (JsonEditor, RenderedJsonField, Code, CodeDiffViewer) are updated to use the hook. No changes to component structure, dynamic height behavior, or any other behavior beyond theme wiring.

How to test

  1. breeze start-airflow --dev-mode --load-example-dags
  2. Visit the DAG Code tab, XCom page, Connections > Edit > Extra field, Trigger DAG dialog, DAG Details page
  3. Toggle between light and dark mode — editor shell colors should smoothly match the surrounding Chakra UI surfaces instead of the default VS Code palette
white_color_dag_codedag_rundag_code_diffScreenshot 2026-04-05 at 12 16 12 PMaudit_logScreenshot 2026-04-05 at 12 21 04 PMxcom
Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 4.6)

Generated-by: Claude Code (Opus 4.6) following the guidelines

@boring-cyborgboring-cyborgBot added the area:UI Related to UI/UX. For Frontend Developers. label Apr 5, 2026
@shivaamshivaam mentioned this pull request Apr 5, 2026
1 task

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just one nit, but directions looks good to me.

Let me know when this is out of draft (fix static checks, CI more generally) and it's ready for a more in depth review + local testing.

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.ts Outdated
@shivaam

Copy link
Copy Markdown
ContributorAuthor

Just one nit, but directions looks good to me.

Let me know when this is out of draft (fix static checks, CI more generally) and it's ready for a more in depth review + local testing.

@pierrejeambrun handled the nits and the PR is ready for local testing

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. Tested locally and working as expected.

IT's also nicely inheriting custom theming:
Overriding the brand color palette (see text selection)
Image

Someone overriding the 'grey' color palette will have something like:

Image

vs

Image

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.ts Outdated
@kaxil
kaxil requested a review from CopilotApril 10, 2026 19:55

CopilotAI 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

Registers custom airflow-light / airflow-dark Monaco themes derived from Chakra UI tokens, and wires them into all Monaco editor usages so editor chrome matches the app’s design system.

Changes:

  • Add useMonacoTheme hook that defines and selects the Monaco theme based on current Chakra color mode.
  • Update all Monaco editor call sites (Editor + DiffEditor) to use the hook’s beforeMount + theme.
  • Add unit tests covering theme selection and one-time registration behavior.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
airflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.tsDefines custom Monaco themes using Chakra CSS variables and exposes beforeMount + theme.
airflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.test.tsTests theme name selection and single registration behavior.
airflow-core/src/airflow/ui/src/context/colorMode/index.tsExports useMonacoTheme from the colorMode barrel.
airflow-core/src/airflow/ui/src/pages/Dag/Code/Code.tsxUses useMonacoTheme for the DAG code viewer Monaco editor.
airflow-core/src/airflow/ui/src/pages/Dag/Code/CodeDiffViewer.tsxUses useMonacoTheme for the DAG code diff Monaco editor.
airflow-core/src/airflow/ui/src/components/JsonEditor.tsxUses useMonacoTheme for the JSON editor component.
airflow-core/src/airflow/ui/src/components/RenderedJsonField.tsxUses useMonacoTheme for read-only rendered JSON Monaco editor instances.

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.test.ts Outdated
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: apache#64253
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
@shivaam
shivaamforce-pushed the fix/monaco-theme-64253 branch from 061ca08 to 7dba46aCompareApril 11, 2026 13:21
@shivaam

Copy link
Copy Markdown
ContributorAuthor

Pushed 7dba46a addressing review feedback:

Canvas → culori for color conversion (@pierrejeambrun)
afterEach(vi.restoreAllMocks()) to prevent mock leak (@Copilot)

pierrejeambrun
pierrejeambrun previously approved these changes Apr 14, 2026

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

My bad, my testing setup was wrong. Working as expected thanks 🎉 , nice one

@pierrejeambrun
pierrejeambrun merged commit bfe46f6 into apache:mainApr 14, 2026
80 checks passed
github-actionsBot pushed a commit that referenced this pull request Apr 14, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

Backport successfully created: v3-2-test

Note: As of Merging PRs targeted for Airflow 3.X
the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.

In matter of doubt please ask in #release-management Slack channel.

StatusBranchResult
v3-2-testPR Link

@jscheffl

Copy link
Copy Markdown
Contributor

Cool! Thanks for this UX improvement!

@shivaam

Copy link
Copy Markdown
ContributorAuthor

Cool! Thanks for this UX improvement!

You are welcome. Happy to contribute:)

vatsrahul1001 pushed a commit that referenced this pull request Apr 23, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
potiuk pushed a commit that referenced this pull request Apr 26, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
potiuk added a commit that referenced this pull request Apr 26, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:UIRelated to UI/UX. For Frontend Developers.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rework style for the monaco-editor

5 participants

@shivaam@jscheffl@pierrejeambrun@vatsrahul1001
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' UI: Rework Monaco editor theme to match Chakra UI palette by shivaam · Pull Request #64748 · apache/airflow · GitHub
Skip to content

UI: Rework Monaco editor theme to match Chakra UI palette - #64748

Merged
pierrejeambrun merged 5 commits into
apache:mainfrom
shivaam:fix/monaco-theme-64253
Apr 14, 2026
Merged

UI: Rework Monaco editor theme to match Chakra UI palette#64748
pierrejeambrun merged 5 commits into
apache:mainfrom
shivaam:fix/monaco-theme-64253

Conversation

@shivaam

@shivaamshivaam commented Apr 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Register custom airflow-light / airflow-dark Monaco themes derived from Chakra UI color tokens so that every Monaco editor in the UI (DAG Code viewer, code diff viewer, JSON editor, RenderedJsonField) visually integrates with the rest of the app instead of using Monaco's default vs / vs-dark themes.

closes: #64253

Open Questions

  1. Design question: I added a module-level themesRegistered flag so defineTheme
    only runs on the first beforeMount. Without it, pages with many editors (e.g.
    XCom table with ~50 rows) re-register themes on every mount. Measured cost without the guard: ~4ms on a 50-editor page. Negligible. Happy to drop the flag for simpler code + tests if you prefer..
  2. Design question: Chakra v3 uses OKLCH, Monaco's defineTheme only accepts
    #rrggbb. I convert by rasterizing a 1x1 canvas pixel and reading back sRGB
    via getImageData. I checked ctx.fillStyle readback — it preserves the OKLCH string unchanged on Chrome 111+, so that path silently fails (this is what PR Rework Monaco editor style to match Chakra UI color palette  #64268 does).

Implementation notes

  • New hook useMonacoTheme (src/context/colorMode/useMonacoTheme.ts) — registers both custom themes exactly once via a module-level flag, returns a stable beforeMount callback and the correct theme name for the current color mode.
  • inherit: true + empty rules — Monaco's default syntax highlighting (keywords, strings, comments) is preserved. Only editor shell colors (background, foreground, gutter, selection, scrollbar, line numbers) are overridden.
  • OKLCH → hex conversion via getImageData — Chakra v3 uses OKLCH colors. ctx.fillStyle readback cannot be relied on because Chrome 111+ preserves the OKLCH string instead of converting to hex, which Monaco would silently ignore.
  • Single registration — themes are registered once per session via a module-level flag so pages with many editor instances (e.g. XCom table with many RenderedJsonField rows) don't pay the cost on every mount.
  • All four Monaco usages (JsonEditor, RenderedJsonField, Code, CodeDiffViewer) are updated to use the hook. No changes to component structure, dynamic height behavior, or any other behavior beyond theme wiring.

How to test

  1. breeze start-airflow --dev-mode --load-example-dags
  2. Visit the DAG Code tab, XCom page, Connections > Edit > Extra field, Trigger DAG dialog, DAG Details page
  3. Toggle between light and dark mode — editor shell colors should smoothly match the surrounding Chakra UI surfaces instead of the default VS Code palette
white_color_dag_codedag_rundag_code_diffScreenshot 2026-04-05 at 12 16 12 PMaudit_logScreenshot 2026-04-05 at 12 21 04 PMxcom
Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 4.6)

Generated-by: Claude Code (Opus 4.6) following the guidelines

@boring-cyborgboring-cyborgBot added the area:UI Related to UI/UX. For Frontend Developers. label Apr 5, 2026
@shivaamshivaam mentioned this pull request Apr 5, 2026
1 task

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just one nit, but directions looks good to me.

Let me know when this is out of draft (fix static checks, CI more generally) and it's ready for a more in depth review + local testing.

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.ts Outdated
@shivaam

Copy link
Copy Markdown
ContributorAuthor

Just one nit, but directions looks good to me.

Let me know when this is out of draft (fix static checks, CI more generally) and it's ready for a more in depth review + local testing.

@pierrejeambrun handled the nits and the PR is ready for local testing

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. Tested locally and working as expected.

IT's also nicely inheriting custom theming:
Overriding the brand color palette (see text selection)
Image

Someone overriding the 'grey' color palette will have something like:

Image

vs

Image

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.ts Outdated
@kaxil
kaxil requested a review from CopilotApril 10, 2026 19:55

CopilotAI 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

Registers custom airflow-light / airflow-dark Monaco themes derived from Chakra UI tokens, and wires them into all Monaco editor usages so editor chrome matches the app’s design system.

Changes:

  • Add useMonacoTheme hook that defines and selects the Monaco theme based on current Chakra color mode.
  • Update all Monaco editor call sites (Editor + DiffEditor) to use the hook’s beforeMount + theme.
  • Add unit tests covering theme selection and one-time registration behavior.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
airflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.tsDefines custom Monaco themes using Chakra CSS variables and exposes beforeMount + theme.
airflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.test.tsTests theme name selection and single registration behavior.
airflow-core/src/airflow/ui/src/context/colorMode/index.tsExports useMonacoTheme from the colorMode barrel.
airflow-core/src/airflow/ui/src/pages/Dag/Code/Code.tsxUses useMonacoTheme for the DAG code viewer Monaco editor.
airflow-core/src/airflow/ui/src/pages/Dag/Code/CodeDiffViewer.tsxUses useMonacoTheme for the DAG code diff Monaco editor.
airflow-core/src/airflow/ui/src/components/JsonEditor.tsxUses useMonacoTheme for the JSON editor component.
airflow-core/src/airflow/ui/src/components/RenderedJsonField.tsxUses useMonacoTheme for read-only rendered JSON Monaco editor instances.

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.test.ts Outdated
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: apache#64253
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
@shivaam
shivaamforce-pushed the fix/monaco-theme-64253 branch from 061ca08 to 7dba46aCompareApril 11, 2026 13:21
@shivaam

Copy link
Copy Markdown
ContributorAuthor

Pushed 7dba46a addressing review feedback:

Canvas → culori for color conversion (@pierrejeambrun)
afterEach(vi.restoreAllMocks()) to prevent mock leak (@Copilot)

pierrejeambrun
pierrejeambrun previously approved these changes Apr 14, 2026

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

My bad, my testing setup was wrong. Working as expected thanks 🎉 , nice one

@pierrejeambrun
pierrejeambrun merged commit bfe46f6 into apache:mainApr 14, 2026
80 checks passed
github-actionsBot pushed a commit that referenced this pull request Apr 14, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

Backport successfully created: v3-2-test

Note: As of Merging PRs targeted for Airflow 3.X
the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.

In matter of doubt please ask in #release-management Slack channel.

StatusBranchResult
v3-2-testPR Link

@jscheffl

Copy link
Copy Markdown
Contributor

Cool! Thanks for this UX improvement!

@shivaam

Copy link
Copy Markdown
ContributorAuthor

Cool! Thanks for this UX improvement!

You are welcome. Happy to contribute:)

vatsrahul1001 pushed a commit that referenced this pull request Apr 23, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
potiuk pushed a commit that referenced this pull request Apr 26, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
potiuk added a commit that referenced this pull request Apr 26, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:UIRelated to UI/UX. For Frontend Developers.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rework style for the monaco-editor

5 participants

@shivaam@jscheffl@pierrejeambrun@vatsrahul1001
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' UI: Rework Monaco editor theme to match Chakra UI palette by shivaam · Pull Request #64748 · apache/airflow · GitHub
Skip to content

UI: Rework Monaco editor theme to match Chakra UI palette - #64748

Merged
pierrejeambrun merged 5 commits into
apache:mainfrom
shivaam:fix/monaco-theme-64253
Apr 14, 2026
Merged

UI: Rework Monaco editor theme to match Chakra UI palette#64748
pierrejeambrun merged 5 commits into
apache:mainfrom
shivaam:fix/monaco-theme-64253

Conversation

@shivaam

@shivaamshivaam commented Apr 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Register custom airflow-light / airflow-dark Monaco themes derived from Chakra UI color tokens so that every Monaco editor in the UI (DAG Code viewer, code diff viewer, JSON editor, RenderedJsonField) visually integrates with the rest of the app instead of using Monaco's default vs / vs-dark themes.

closes: #64253

Open Questions

  1. Design question: I added a module-level themesRegistered flag so defineTheme
    only runs on the first beforeMount. Without it, pages with many editors (e.g.
    XCom table with ~50 rows) re-register themes on every mount. Measured cost without the guard: ~4ms on a 50-editor page. Negligible. Happy to drop the flag for simpler code + tests if you prefer..
  2. Design question: Chakra v3 uses OKLCH, Monaco's defineTheme only accepts
    #rrggbb. I convert by rasterizing a 1x1 canvas pixel and reading back sRGB
    via getImageData. I checked ctx.fillStyle readback — it preserves the OKLCH string unchanged on Chrome 111+, so that path silently fails (this is what PR Rework Monaco editor style to match Chakra UI color palette  #64268 does).

Implementation notes

  • New hook useMonacoTheme (src/context/colorMode/useMonacoTheme.ts) — registers both custom themes exactly once via a module-level flag, returns a stable beforeMount callback and the correct theme name for the current color mode.
  • inherit: true + empty rules — Monaco's default syntax highlighting (keywords, strings, comments) is preserved. Only editor shell colors (background, foreground, gutter, selection, scrollbar, line numbers) are overridden.
  • OKLCH → hex conversion via getImageData — Chakra v3 uses OKLCH colors. ctx.fillStyle readback cannot be relied on because Chrome 111+ preserves the OKLCH string instead of converting to hex, which Monaco would silently ignore.
  • Single registration — themes are registered once per session via a module-level flag so pages with many editor instances (e.g. XCom table with many RenderedJsonField rows) don't pay the cost on every mount.
  • All four Monaco usages (JsonEditor, RenderedJsonField, Code, CodeDiffViewer) are updated to use the hook. No changes to component structure, dynamic height behavior, or any other behavior beyond theme wiring.

How to test

  1. breeze start-airflow --dev-mode --load-example-dags
  2. Visit the DAG Code tab, XCom page, Connections > Edit > Extra field, Trigger DAG dialog, DAG Details page
  3. Toggle between light and dark mode — editor shell colors should smoothly match the surrounding Chakra UI surfaces instead of the default VS Code palette
white_color_dag_codedag_rundag_code_diffScreenshot 2026-04-05 at 12 16 12 PMaudit_logScreenshot 2026-04-05 at 12 21 04 PMxcom
Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 4.6)

Generated-by: Claude Code (Opus 4.6) following the guidelines

@boring-cyborgboring-cyborgBot added the area:UI Related to UI/UX. For Frontend Developers. label Apr 5, 2026
@shivaamshivaam mentioned this pull request Apr 5, 2026
1 task

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just one nit, but directions looks good to me.

Let me know when this is out of draft (fix static checks, CI more generally) and it's ready for a more in depth review + local testing.

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.ts Outdated
@shivaam

Copy link
Copy Markdown
ContributorAuthor

Just one nit, but directions looks good to me.

Let me know when this is out of draft (fix static checks, CI more generally) and it's ready for a more in depth review + local testing.

@pierrejeambrun handled the nits and the PR is ready for local testing

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. Tested locally and working as expected.

IT's also nicely inheriting custom theming:
Overriding the brand color palette (see text selection)
Image

Someone overriding the 'grey' color palette will have something like:

Image

vs

Image

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.ts Outdated
@kaxil
kaxil requested a review from CopilotApril 10, 2026 19:55

CopilotAI 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

Registers custom airflow-light / airflow-dark Monaco themes derived from Chakra UI tokens, and wires them into all Monaco editor usages so editor chrome matches the app’s design system.

Changes:

  • Add useMonacoTheme hook that defines and selects the Monaco theme based on current Chakra color mode.
  • Update all Monaco editor call sites (Editor + DiffEditor) to use the hook’s beforeMount + theme.
  • Add unit tests covering theme selection and one-time registration behavior.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
airflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.tsDefines custom Monaco themes using Chakra CSS variables and exposes beforeMount + theme.
airflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.test.tsTests theme name selection and single registration behavior.
airflow-core/src/airflow/ui/src/context/colorMode/index.tsExports useMonacoTheme from the colorMode barrel.
airflow-core/src/airflow/ui/src/pages/Dag/Code/Code.tsxUses useMonacoTheme for the DAG code viewer Monaco editor.
airflow-core/src/airflow/ui/src/pages/Dag/Code/CodeDiffViewer.tsxUses useMonacoTheme for the DAG code diff Monaco editor.
airflow-core/src/airflow/ui/src/components/JsonEditor.tsxUses useMonacoTheme for the JSON editor component.
airflow-core/src/airflow/ui/src/components/RenderedJsonField.tsxUses useMonacoTheme for read-only rendered JSON Monaco editor instances.

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.test.ts Outdated
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: apache#64253
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
@shivaam
shivaamforce-pushed the fix/monaco-theme-64253 branch from 061ca08 to 7dba46aCompareApril 11, 2026 13:21
@shivaam

Copy link
Copy Markdown
ContributorAuthor

Pushed 7dba46a addressing review feedback:

Canvas → culori for color conversion (@pierrejeambrun)
afterEach(vi.restoreAllMocks()) to prevent mock leak (@Copilot)

pierrejeambrun
pierrejeambrun previously approved these changes Apr 14, 2026

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

My bad, my testing setup was wrong. Working as expected thanks 🎉 , nice one

@pierrejeambrun
pierrejeambrun merged commit bfe46f6 into apache:mainApr 14, 2026
80 checks passed
github-actionsBot pushed a commit that referenced this pull request Apr 14, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

Backport successfully created: v3-2-test

Note: As of Merging PRs targeted for Airflow 3.X
the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.

In matter of doubt please ask in #release-management Slack channel.

StatusBranchResult
v3-2-testPR Link

@jscheffl

Copy link
Copy Markdown
Contributor

Cool! Thanks for this UX improvement!

@shivaam

Copy link
Copy Markdown
ContributorAuthor

Cool! Thanks for this UX improvement!

You are welcome. Happy to contribute:)

vatsrahul1001 pushed a commit that referenced this pull request Apr 23, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
potiuk pushed a commit that referenced this pull request Apr 26, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
potiuk added a commit that referenced this pull request Apr 26, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:UIRelated to UI/UX. For Frontend Developers.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rework style for the monaco-editor

5 participants

@shivaam@jscheffl@pierrejeambrun@vatsrahul1001
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' UI: Rework Monaco editor theme to match Chakra UI palette by shivaam · Pull Request #64748 · apache/airflow · GitHub
Skip to content

UI: Rework Monaco editor theme to match Chakra UI palette - #64748

Merged
pierrejeambrun merged 5 commits into
apache:mainfrom
shivaam:fix/monaco-theme-64253
Apr 14, 2026
Merged

UI: Rework Monaco editor theme to match Chakra UI palette#64748
pierrejeambrun merged 5 commits into
apache:mainfrom
shivaam:fix/monaco-theme-64253

Conversation

@shivaam

@shivaamshivaam commented Apr 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Register custom airflow-light / airflow-dark Monaco themes derived from Chakra UI color tokens so that every Monaco editor in the UI (DAG Code viewer, code diff viewer, JSON editor, RenderedJsonField) visually integrates with the rest of the app instead of using Monaco's default vs / vs-dark themes.

closes: #64253

Open Questions

  1. Design question: I added a module-level themesRegistered flag so defineTheme
    only runs on the first beforeMount. Without it, pages with many editors (e.g.
    XCom table with ~50 rows) re-register themes on every mount. Measured cost without the guard: ~4ms on a 50-editor page. Negligible. Happy to drop the flag for simpler code + tests if you prefer..
  2. Design question: Chakra v3 uses OKLCH, Monaco's defineTheme only accepts
    #rrggbb. I convert by rasterizing a 1x1 canvas pixel and reading back sRGB
    via getImageData. I checked ctx.fillStyle readback — it preserves the OKLCH string unchanged on Chrome 111+, so that path silently fails (this is what PR Rework Monaco editor style to match Chakra UI color palette  #64268 does).

Implementation notes

  • New hook useMonacoTheme (src/context/colorMode/useMonacoTheme.ts) — registers both custom themes exactly once via a module-level flag, returns a stable beforeMount callback and the correct theme name for the current color mode.
  • inherit: true + empty rules — Monaco's default syntax highlighting (keywords, strings, comments) is preserved. Only editor shell colors (background, foreground, gutter, selection, scrollbar, line numbers) are overridden.
  • OKLCH → hex conversion via getImageData — Chakra v3 uses OKLCH colors. ctx.fillStyle readback cannot be relied on because Chrome 111+ preserves the OKLCH string instead of converting to hex, which Monaco would silently ignore.
  • Single registration — themes are registered once per session via a module-level flag so pages with many editor instances (e.g. XCom table with many RenderedJsonField rows) don't pay the cost on every mount.
  • All four Monaco usages (JsonEditor, RenderedJsonField, Code, CodeDiffViewer) are updated to use the hook. No changes to component structure, dynamic height behavior, or any other behavior beyond theme wiring.

How to test

  1. breeze start-airflow --dev-mode --load-example-dags
  2. Visit the DAG Code tab, XCom page, Connections > Edit > Extra field, Trigger DAG dialog, DAG Details page
  3. Toggle between light and dark mode — editor shell colors should smoothly match the surrounding Chakra UI surfaces instead of the default VS Code palette
white_color_dag_codedag_rundag_code_diffScreenshot 2026-04-05 at 12 16 12 PMaudit_logScreenshot 2026-04-05 at 12 21 04 PMxcom
Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 4.6)

Generated-by: Claude Code (Opus 4.6) following the guidelines

@boring-cyborgboring-cyborgBot added the area:UI Related to UI/UX. For Frontend Developers. label Apr 5, 2026
@shivaamshivaam mentioned this pull request Apr 5, 2026
1 task

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just one nit, but directions looks good to me.

Let me know when this is out of draft (fix static checks, CI more generally) and it's ready for a more in depth review + local testing.

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.ts Outdated
@shivaam

Copy link
Copy Markdown
ContributorAuthor

Just one nit, but directions looks good to me.

Let me know when this is out of draft (fix static checks, CI more generally) and it's ready for a more in depth review + local testing.

@pierrejeambrun handled the nits and the PR is ready for local testing

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. Tested locally and working as expected.

IT's also nicely inheriting custom theming:
Overriding the brand color palette (see text selection)
Image

Someone overriding the 'grey' color palette will have something like:

Image

vs

Image

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.ts Outdated
@kaxil
kaxil requested a review from CopilotApril 10, 2026 19:55

CopilotAI 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

Registers custom airflow-light / airflow-dark Monaco themes derived from Chakra UI tokens, and wires them into all Monaco editor usages so editor chrome matches the app’s design system.

Changes:

  • Add useMonacoTheme hook that defines and selects the Monaco theme based on current Chakra color mode.
  • Update all Monaco editor call sites (Editor + DiffEditor) to use the hook’s beforeMount + theme.
  • Add unit tests covering theme selection and one-time registration behavior.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
airflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.tsDefines custom Monaco themes using Chakra CSS variables and exposes beforeMount + theme.
airflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.test.tsTests theme name selection and single registration behavior.
airflow-core/src/airflow/ui/src/context/colorMode/index.tsExports useMonacoTheme from the colorMode barrel.
airflow-core/src/airflow/ui/src/pages/Dag/Code/Code.tsxUses useMonacoTheme for the DAG code viewer Monaco editor.
airflow-core/src/airflow/ui/src/pages/Dag/Code/CodeDiffViewer.tsxUses useMonacoTheme for the DAG code diff Monaco editor.
airflow-core/src/airflow/ui/src/components/JsonEditor.tsxUses useMonacoTheme for the JSON editor component.
airflow-core/src/airflow/ui/src/components/RenderedJsonField.tsxUses useMonacoTheme for read-only rendered JSON Monaco editor instances.

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.test.ts Outdated
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: apache#64253
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
@shivaam
shivaamforce-pushed the fix/monaco-theme-64253 branch from 061ca08 to 7dba46aCompareApril 11, 2026 13:21
@shivaam

Copy link
Copy Markdown
ContributorAuthor

Pushed 7dba46a addressing review feedback:

Canvas → culori for color conversion (@pierrejeambrun)
afterEach(vi.restoreAllMocks()) to prevent mock leak (@Copilot)

pierrejeambrun
pierrejeambrun previously approved these changes Apr 14, 2026

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

My bad, my testing setup was wrong. Working as expected thanks 🎉 , nice one

@pierrejeambrun
pierrejeambrun merged commit bfe46f6 into apache:mainApr 14, 2026
80 checks passed
github-actionsBot pushed a commit that referenced this pull request Apr 14, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

Backport successfully created: v3-2-test

Note: As of Merging PRs targeted for Airflow 3.X
the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.

In matter of doubt please ask in #release-management Slack channel.

StatusBranchResult
v3-2-testPR Link

@jscheffl

Copy link
Copy Markdown
Contributor

Cool! Thanks for this UX improvement!

@shivaam

Copy link
Copy Markdown
ContributorAuthor

Cool! Thanks for this UX improvement!

You are welcome. Happy to contribute:)

vatsrahul1001 pushed a commit that referenced this pull request Apr 23, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
potiuk pushed a commit that referenced this pull request Apr 26, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
potiuk added a commit that referenced this pull request Apr 26, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:UIRelated to UI/UX. For Frontend Developers.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rework style for the monaco-editor

5 participants

@shivaam@jscheffl@pierrejeambrun@vatsrahul1001
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); UI: Rework Monaco editor theme to match Chakra UI palette by shivaam · Pull Request #64748 · apache/airflow · GitHub
Skip to content

UI: Rework Monaco editor theme to match Chakra UI palette - #64748

Merged
pierrejeambrun merged 5 commits into
apache:mainfrom
shivaam:fix/monaco-theme-64253
Apr 14, 2026
Merged

UI: Rework Monaco editor theme to match Chakra UI palette#64748
pierrejeambrun merged 5 commits into
apache:mainfrom
shivaam:fix/monaco-theme-64253

Conversation

@shivaam

@shivaamshivaam commented Apr 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Register custom airflow-light / airflow-dark Monaco themes derived from Chakra UI color tokens so that every Monaco editor in the UI (DAG Code viewer, code diff viewer, JSON editor, RenderedJsonField) visually integrates with the rest of the app instead of using Monaco's default vs / vs-dark themes.

closes: #64253

Open Questions

  1. Design question: I added a module-level themesRegistered flag so defineTheme
    only runs on the first beforeMount. Without it, pages with many editors (e.g.
    XCom table with ~50 rows) re-register themes on every mount. Measured cost without the guard: ~4ms on a 50-editor page. Negligible. Happy to drop the flag for simpler code + tests if you prefer..
  2. Design question: Chakra v3 uses OKLCH, Monaco's defineTheme only accepts
    #rrggbb. I convert by rasterizing a 1x1 canvas pixel and reading back sRGB
    via getImageData. I checked ctx.fillStyle readback — it preserves the OKLCH string unchanged on Chrome 111+, so that path silently fails (this is what PR Rework Monaco editor style to match Chakra UI color palette  #64268 does).

Implementation notes

  • New hook useMonacoTheme (src/context/colorMode/useMonacoTheme.ts) — registers both custom themes exactly once via a module-level flag, returns a stable beforeMount callback and the correct theme name for the current color mode.
  • inherit: true + empty rules — Monaco's default syntax highlighting (keywords, strings, comments) is preserved. Only editor shell colors (background, foreground, gutter, selection, scrollbar, line numbers) are overridden.
  • OKLCH → hex conversion via getImageData — Chakra v3 uses OKLCH colors. ctx.fillStyle readback cannot be relied on because Chrome 111+ preserves the OKLCH string instead of converting to hex, which Monaco would silently ignore.
  • Single registration — themes are registered once per session via a module-level flag so pages with many editor instances (e.g. XCom table with many RenderedJsonField rows) don't pay the cost on every mount.
  • All four Monaco usages (JsonEditor, RenderedJsonField, Code, CodeDiffViewer) are updated to use the hook. No changes to component structure, dynamic height behavior, or any other behavior beyond theme wiring.

How to test

  1. breeze start-airflow --dev-mode --load-example-dags
  2. Visit the DAG Code tab, XCom page, Connections > Edit > Extra field, Trigger DAG dialog, DAG Details page
  3. Toggle between light and dark mode — editor shell colors should smoothly match the surrounding Chakra UI surfaces instead of the default VS Code palette
white_color_dag_codedag_rundag_code_diffScreenshot 2026-04-05 at 12 16 12 PMaudit_logScreenshot 2026-04-05 at 12 21 04 PMxcom
Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 4.6)

Generated-by: Claude Code (Opus 4.6) following the guidelines

@boring-cyborgboring-cyborgBot added the area:UI Related to UI/UX. For Frontend Developers. label Apr 5, 2026
@shivaamshivaam mentioned this pull request Apr 5, 2026
1 task

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just one nit, but directions looks good to me.

Let me know when this is out of draft (fix static checks, CI more generally) and it's ready for a more in depth review + local testing.

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.ts Outdated
@shivaam

Copy link
Copy Markdown
ContributorAuthor

Just one nit, but directions looks good to me.

Let me know when this is out of draft (fix static checks, CI more generally) and it's ready for a more in depth review + local testing.

@pierrejeambrun handled the nits and the PR is ready for local testing

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. Tested locally and working as expected.

IT's also nicely inheriting custom theming:
Overriding the brand color palette (see text selection)
Image

Someone overriding the 'grey' color palette will have something like:

Image

vs

Image

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.ts Outdated
@kaxil
kaxil requested a review from CopilotApril 10, 2026 19:55

CopilotAI 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

Registers custom airflow-light / airflow-dark Monaco themes derived from Chakra UI tokens, and wires them into all Monaco editor usages so editor chrome matches the app’s design system.

Changes:

  • Add useMonacoTheme hook that defines and selects the Monaco theme based on current Chakra color mode.
  • Update all Monaco editor call sites (Editor + DiffEditor) to use the hook’s beforeMount + theme.
  • Add unit tests covering theme selection and one-time registration behavior.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
airflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.tsDefines custom Monaco themes using Chakra CSS variables and exposes beforeMount + theme.
airflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.test.tsTests theme name selection and single registration behavior.
airflow-core/src/airflow/ui/src/context/colorMode/index.tsExports useMonacoTheme from the colorMode barrel.
airflow-core/src/airflow/ui/src/pages/Dag/Code/Code.tsxUses useMonacoTheme for the DAG code viewer Monaco editor.
airflow-core/src/airflow/ui/src/pages/Dag/Code/CodeDiffViewer.tsxUses useMonacoTheme for the DAG code diff Monaco editor.
airflow-core/src/airflow/ui/src/components/JsonEditor.tsxUses useMonacoTheme for the JSON editor component.
airflow-core/src/airflow/ui/src/components/RenderedJsonField.tsxUses useMonacoTheme for read-only rendered JSON Monaco editor instances.

Comment threadairflow-core/src/airflow/ui/src/context/colorMode/useMonacoTheme.test.ts Outdated
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: apache#64253
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
@shivaam
shivaamforce-pushed the fix/monaco-theme-64253 branch from 061ca08 to 7dba46aCompareApril 11, 2026 13:21
@shivaam

Copy link
Copy Markdown
ContributorAuthor

Pushed 7dba46a addressing review feedback:

Canvas → culori for color conversion (@pierrejeambrun)
afterEach(vi.restoreAllMocks()) to prevent mock leak (@Copilot)

pierrejeambrun
pierrejeambrun previously approved these changes Apr 14, 2026

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

My bad, my testing setup was wrong. Working as expected thanks 🎉 , nice one

@pierrejeambrun
pierrejeambrun merged commit bfe46f6 into apache:mainApr 14, 2026
80 checks passed
github-actionsBot pushed a commit that referenced this pull request Apr 14, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

Backport successfully created: v3-2-test

Note: As of Merging PRs targeted for Airflow 3.X
the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.

In matter of doubt please ask in #release-management Slack channel.

StatusBranchResult
v3-2-testPR Link

@jscheffl

Copy link
Copy Markdown
Contributor

Cool! Thanks for this UX improvement!

@shivaam

Copy link
Copy Markdown
ContributorAuthor

Cool! Thanks for this UX improvement!

You are welcome. Happy to contribute:)

vatsrahul1001 pushed a commit that referenced this pull request Apr 23, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
potiuk pushed a commit that referenced this pull request Apr 26, 2026
…#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
potiuk added a commit that referenced this pull request Apr 26, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
…#64748) (#65228)
* [v3-2-test] UI: Rework Monaco editor theme to match Chakra UI palette (#64748)
* UI: Rework Monaco editor theme to match Chakra UI palette
Register custom airflow-light and airflow-dark Monaco themes derived
from Chakra UI color tokens so that the DAG Code viewer, diff viewer,
and JSON editors visually integrate with the rest of the app instead
of using Monaco's default vs/vs-dark themes.
The new useMonacoTheme hook rasterizes a single pixel through a 2D
canvas and reads it back via getImageData to convert Chakra's OKLCH
color values into the #rrggbb strings that Monaco's defineTheme
accepts — ctx.fillStyle readback cannot be used because modern
Chrome preserves the original OKLCH string. Themes are registered
once via a module-level flag and then passed to every Monaco editor
via the beforeMount callback.
closes: #64253
* UI: Remove unnecessary useCallback in useMonacoTheme
Address review feedback: React Compiler handles memoization,
so the useCallback wrapper around defineAirflowMonacoThemes
is redundant. Pass the function reference directly instead.
Also fix prettier formatting in tests.
* UI: Use culori for Monaco theme color conversion
Address review feedback: the canvas-based cssVarToHex was brittle
(depended on Canvas2D rendering and browser-specific fillStyle
behavior, and required canvas mocking in happy-dom tests). Replace
it with culori's parse/formatHex, which handles OKLCH and other
modern color spaces directly with no DOM rasterization.
Also add afterEach(vi.restoreAllMocks()) to the tests so the
getComputedStyle spy does not leak between runs.
* UI: Fix codespell typo in useMonacoTheme comment
unparseable -> unparsable.
(cherry picked from commit bfe46f6)
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
* [v3-2-test] Bump actions/github-script in the github-actions-updates group (#65150) (#65160)
Bumps the github-actions-updates group with 1 update: [actions/github-script](https://github.com/actions/github-script).
Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)
(cherry picked from commit e5a047c)
---
updated-dependencies:
- dependency-name: actions/github-script
dependency-version: 9.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-updates
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [v3-2-test] Added breeze generate issue content for airflow-ctl (#65042) (#65241)
* Add breeze generate issue content for airflow-ctl
* add new command to doc
(cherry picked from commit b24538b)
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
* [v3-2-test] Run release calendar verification on its own schedule (#65118) (#65242)
* Move release calendar verification to its own scheduled workflow
Run dev/verify_release_calendar.py from a dedicated daily scheduled
workflow instead of as a canary job in the main CI pipeline, and
notify the #release-management Slack channel when the check fails so
the issue is surfaced to release managers directly.
* Include wiki and calendar links in release calendar Slack alert
(cherry picked from commit 048e9a1)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Shivam Rastogi <6463385+shivaam@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Co-authored-by: Justin Pakzad <114518232+justinpakzad@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:UIRelated to UI/UX. For Frontend Developers.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rework style for the monaco-editor

5 participants

@shivaam@jscheffl@pierrejeambrun@vatsrahul1001