Skip to content

fix: honor dark mode for monaco editor#4650

Merged
devinat1 merged 4 commits intomainfrom
devin/eng-2973-monaco-fix
Sep 8, 2025
Merged

fix: honor dark mode for monaco editor#4650
devinat1 merged 4 commits intomainfrom
devin/eng-2973-monaco-fix

Conversation

@devinat1
Copy link
Contributor

@devinat1 devinat1 commented Sep 4, 2025

Synchronize the Monaco editor's theme with the application's current theme (light or dark mode)

@vercel
Copy link

vercel bot commented Sep 4, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
helicone Ready Ready Preview Comment Sep 8, 2025 5:55pm
helicone-eu Ready Ready Preview Comment Sep 8, 2025 5:55pm
1 Skipped Deployment
Project Deployment Preview Comments Updated (UTC)
helicone-bifrost Skipped Skipped Sep 8, 2025 5:55pm

@claude
Copy link
Contributor

claude bot commented Sep 4, 2025

Claude finished @devinat1's task —— View job


Code Review: Monaco Editor Dark Mode Implementation

Confidence Score: 8/10 - This is a solid implementation that safely adds dark mode support to the Monaco editor with minimal risk.

Summary

The implementation successfully synchronizes the Monaco editor's theme with the application's theme state using next-themes. The key changes include custom theme definitions with transparent backgrounds and dynamic theme switching via useEffect. The code is functional and follows React best practices, though there are some minor areas for improvement.

Detailed Analysis

Code Quality & Best Practices ✅

Strengths:

  • Proper use of next-themes library integration (web/components/templates/hql/hqlPage.tsx:31,38)
  • Appropriate useEffect dependency array with currentTheme (web/components/templates/hql/hqlPage.tsx:177)
  • Safe window object checking with typeof window === "undefined" guard (web/components/templates/hql/hqlPage.tsx:148)
  • Error handling with try-catch for theme definition to prevent duplicate registration (web/components/templates/hql/hqlPage.tsx:153-172)
  • Transparent background implementation using 8-digit hex (#00000000) is correct for RGBA format

Areas for Improvement:

  • Code Duplication: Theme definition logic is duplicated between useEffect (lines 154-169) and onMount (missing but referenced in comment at line 372-376). Consider extracting into a shared function.
  • Theme Prop Inconsistency: The Editor component uses different theme values:
    • theme prop uses basic themes: vs-dark vs vs (line 352)
    • useEffect and onMount apply custom themes: custom-dark vs custom-light
      This could cause visual inconsistency during initial render before useEffect runs.

Potential Bugs & Issues ⚠️

  1. Race Condition Risk: The useEffect accesses (window as any).monaco directly, but Monaco might not be loaded yet. The useMonaco() hook (line 40) should be used instead for safer access.

  2. Theme Application Timing: There's a potential flash of incorrect theme during component mount since the Editor's theme prop doesn't use the custom themes initially.

  3. Missing Theme Definition in onMount: The comment at line 372 mentions "Define and apply transparent background themes" but the actual theme definition code is missing in the onMount handler, unlike the useEffect.

Performance Considerations ✅

  • Efficient Re-renders: The useEffect properly depends on currentTheme only, preventing unnecessary executions
  • Idempotent Theme Definition: The try-catch pattern ensures themes are only defined once, preventing memory leaks
  • No Performance Impact: The theme switching is lightweight and doesn't affect editor content or functionality

Security Concerns ✅

  • No Security Issues: The implementation doesn't introduce any security vulnerabilities
  • Safe DOM Access: Proper window object checking prevents SSR issues
  • Type Safety: Uses TypeScript properly, though (window as any).monaco could be more type-safe

Suggested Improvements

  1. Extract Theme Definition Logic:
const defineCustomThemes = (monaco: any) => {
  try {
    monaco.editor.defineTheme("custom-dark", {
      base: "vs-dark",
      inherit: true,
      rules: [],
      colors: { "editor.background": "#00000000" },
    });
    monaco.editor.defineTheme("custom-light", {
      base: "vs",
      inherit: true, 
      rules: [],
      colors: { "editor.background": "#00000000" },
    });
  } catch (e) {
    // themes may already be defined
  }
};
  1. Use Consistent Theme Names: Update the Editor's theme prop to use the custom themes:
theme={currentTheme === "dark" ? "custom-dark" : "custom-light"}
  1. Safer Monaco Access: Use the useMonaco() hook result instead of window access:
useEffect(() => {
  if (!monaco) return;
  defineCustomThemes(monaco);
  monaco.editor.setTheme(currentTheme === "dark" ? "custom-dark" : "custom-light");
}, [monaco, currentTheme]);

Recommendation

This PR is ready to merge with the current implementation. While there are opportunities for improvement (code deduplication, theme consistency), the functionality works correctly and the issues are minor. The transparent background approach properly integrates with the application's design system.


@vercel vercel bot temporarily deployed to Preview – helicone-bifrost September 4, 2025 03:00 Inactive
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Greptile Summary

This PR adds dark mode support to the Monaco SQL editor in the HQL (Helicone Query Language) page. The implementation synchronizes the Monaco editor's theme with the application's current theme state using the next-themes library.

The key changes include:

  1. Theme Hook Integration: Imports and uses the useTheme hook from next-themes to access the current theme state
  2. Custom Theme Definitions: Creates custom Monaco themes (custom-dark and custom-light) with transparent backgrounds (#00000000) to better integrate with the application's styling system
  3. Dynamic Theme Switching: Implements a useEffect hook that applies the appropriate Monaco theme whenever the application's theme changes
  4. Editor Configuration: Sets the Monaco Editor's theme prop to match the current theme (vs-dark or vs-light)
  5. Mount Handler: Duplicates the theme definition logic in the onMount handler to ensure themes are available when the editor initializes

This change integrates with Helicone's existing theme management system, which uses next-themes and includes conditional theme forcing for authentication pages (as seen in themeContext.tsx). The HQL page is a SQL query interface used for querying Helicone's data, and this enhancement ensures a consistent user experience across light and dark modes.

Confidence score: 4/5

  • This PR is safe to merge with minimal risk of breaking functionality
  • Score reflects solid implementation using established patterns, though there's minor code duplication
  • Pay attention to the Monaco editor initialization timing and theme definition logic

1 file reviewed, 1 comment

Edit Code Review Bot Settings | Greptile

Comment on lines +379 to +387
"editor.background": "#00000000",
},
});
monaco.editor.defineTheme("custom-light", {
base: "vs",
inherit: true,
rules: [],
colors: {
"editor.background": "#00000000",
Copy link
Contributor

Choose a reason for hiding this comment

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

i did not test this locally but isn't #00000000 black? so why is it set to that for the custom-light theme?

Copy link
Contributor

Choose a reason for hiding this comment

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

agreed - maybe we make it transparent like the other manaco editor we have

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the 00 at the end represents 0% alpha (fully transparent) in the 8-digit hex color format (#RRGGBBAA).
It seems to work on my testing. Where is the other monaco editor?

Copy link
Contributor

Choose a reason for hiding this comment

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

ah gotcha i didn't realize the difference between 6 vs 8 digit. if you tested and it works, then LGTM!

@vercel vercel bot temporarily deployed to Preview – helicone-bifrost September 8, 2025 17:51 Inactive
@devinat1 devinat1 merged commit ba762c2 into main Sep 8, 2025
8 of 10 checks passed
@devinat1 devinat1 deleted the devin/eng-2973-monaco-fix branch September 8, 2025 17:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants