Skip to content

Switch to Monaco Editor#3857

Draft
RichDom2185 wants to merge 9 commits into
masterfrom
monaco-editor
Draft

Switch to Monaco Editor#3857
RichDom2185 wants to merge 9 commits into
masterfrom
monaco-editor

Conversation

@RichDom2185
Copy link
Copy Markdown
Member

Description

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update
  • Code quality improvements

How to test

Checklist

  • I have tested this code
  • I have updated the documentation

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request integrates the Monaco editor into the workspace as a feature-flagged alternative to the Ace editor. It adds the MonacoEditor component, a custom theme for visual parity, and necessary environment setup for workers. Review feedback suggests performance optimizations using useMemo and useCallback to prevent unnecessary re-renders, removing a hardcoded DOM ID to avoid conflicts, and expanding worker configuration to support advanced language features like IntelliSense.

@@ -0,0 +1,73 @@
import { Card } from '@blueprintjs/core';
import MonacoReactEditor from '@monaco-editor/react';
import { useCallback } from 'react';
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.

medium

Add useMemo to the React imports to support memoizing the editor options.

Suggested change
import { useCallback } from 'react';
import { useCallback, useMemo } from 'react';

Comment on lines +33 to +41
const handleChange = useCallback(
(value: string | undefined, event: unknown) => {
const newValue = value ?? '';
props.handleEditorValueChange(props.editorTabIndex, newValue);
props.handleUpdateHasUnsavedChanges?.(true);
props.onChange?.(newValue, event);
},
[props]
);
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.

medium

The useCallback hook uses props as a dependency. Since props is a new object created on every render in the parent EditorContainer, this callback will be recreated on every render, defeating the purpose of memoization. It is better to destructure the specific functions and values needed from props and use them as dependencies.

Suggested change
const handleChange = useCallback(
(value: string | undefined, event: unknown) => {
const newValue = value ?? '';
props.handleEditorValueChange(props.editorTabIndex, newValue);
props.handleUpdateHasUnsavedChanges?.(true);
props.onChange?.(newValue, event);
},
[props]
);
const { handleEditorValueChange, editorTabIndex, handleUpdateHasUnsavedChanges, onChange } = props;
const handleChange = useCallback(
(value: string | undefined, event: unknown) => {
const newValue = value ?? '';
handleEditorValueChange(editorTabIndex, newValue);
handleUpdateHasUnsavedChanges?.(true);
onChange?.(newValue, event);
},
[handleEditorValueChange, editorTabIndex, handleUpdateHasUnsavedChanges, onChange]
);


return (
<Card className="Editor">
<div className="row editor-react-ace" data-testid="Editor" id="editor-react-ace">
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.

medium

Using a hardcoded id="editor-react-ace" can lead to duplicate IDs in the DOM if multiple editor tabs are rendered simultaneously. Consider removing the ID if it's not strictly required for external scripts or global CSS targeting.

Suggested change
<div className="row editor-react-ace" data-testid="Editor" id="editor-react-ace">
<div className="row editor-react-ace" data-testid="Editor">

Comment on lines +51 to +63
options={{
fontFamily: "'Inconsolata', 'Consolas', monospace",
fontSize: 17,
folding: false,
glyphMargin: false,
hover: { enabled: false },
lineHeight: 17,
lineNumbersMinChars: 4,
minimap: { enabled: false },
readOnly: props.sessionDetails?.readOnly ?? false,
renderLineHighlight: 'none',
scrollBeyondLastLine: false,
}}
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.

medium

The options object is created inline on every render. This can cause the MonacoReactEditor component to perform unnecessary internal updates. Consider memoizing this object using useMemo.

Suggested change
options={{
fontFamily: "'Inconsolata', 'Consolas', monospace",
fontSize: 17,
folding: false,
glyphMargin: false,
hover: { enabled: false },
lineHeight: 17,
lineNumbersMinChars: 4,
minimap: { enabled: false },
readOnly: props.sessionDetails?.readOnly ?? false,
renderLineHighlight: 'none',
scrollBeyondLastLine: false,
}}
options={useMemo(() => ({
fontFamily: "'Inconsolata', 'Consolas', monospace",
fontSize: 17,
folding: false,
glyphMargin: false,
hover: { enabled: false },
lineHeight: 17,
lineNumbersMinChars: 4,
minimap: { enabled: false },
readOnly: props.sessionDetails?.readOnly ?? false,
renderLineHighlight: 'none',
scrollBeyondLastLine: false,
}), [props.sessionDetails?.readOnly])}

Comment on lines +29 to +35
(self as MonacoEnvironmentGlobal).MonacoEnvironment = {
getWorker: () => {
return new Worker(new URL('monaco-editor/esm/vs/editor/editor.worker.js', import.meta.url), {
type: 'module'
});
}
};
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.

medium

The current getWorker implementation always returns the base editor worker. For full language support (like intellisense and validation) in languages like TypeScript, JavaScript, JSON, CSS, and HTML, it is recommended to provide the corresponding specialized workers based on the label argument.

};

monaco.editor.defineTheme(SOURCE_MONACO_THEME, sourceTheme);
monaco.editor.setTheme(SOURCE_MONACO_THEME);
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.

medium

Setting the theme globally using monaco.editor.setTheme is redundant because the MonacoEditor component explicitly sets the theme via the theme prop. This global call should be removed to avoid unintended side effects and maintain consistency with the component-based configuration.

References
  1. Remove explicit function calls that are made redundant by a more general, encompassing mechanism.

@sayomaki sayomaki marked this pull request as ready for review May 14, 2026 06:31
@sayomaki sayomaki marked this pull request as draft May 14, 2026 06:32
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