Add a custom theme to Monaco Editor for React

How to add a custom Visual Studio Code theme to Monaco Editor for React and custom snippets.

Tutorial
Edit on GitHub

Prepare our Vite project with React

  1. Run the following command to create a new React project with Vite:
pnpm create vite@latest
√ Project name: ... my-monaco-editor
√ Select a framework: » React
√ Select a variant: » TypeScript + SWC
  1. Install dependencies:
pnpm i

Add Monaco Editor to our project

  1. Install the Monaco Editor for React package:
pnpm i @monaco-editor/react -E
  1. Create a new file called MonacoEditor.tsx in the src/ folder:
const MyMonacoEditor = () => {
  return <div>CustomEditor</div>;
};

export default MyMonacoEditor;
  1. Create a new Editor component and import Monaco type (we will use it later):
import { Editor, type Monaco } from '@monaco-editor/react';

const MyMonacoEditor = () => {
  return <Editor width="100%" height="100vh" />;
};

export default MyMonacoEditor;

Prepare our custom Monaco Theme

In our case, we will add One Dark Pro theme to Monaco Editor, you can choose any other theme from the VS Code Marketplace.

  1. Create a new file called onedarkpro.json in the src/ folder:
📂 src
|- 📂 theme
    |- 📄 onedarkpro.json
  1. Copy the source code of the theme from Github Repository.
  2. To make the properties of the VS Code theme the same as in Monaco Editor, we are going to use vsctim utility. Paste the content of the theme into the utility (left side) and click on the “Convert Theme” button. Then, copy the content from the left side and paste it into the onedarkpro.json file.
  3. In the onedarkpro.json file, delete base and inherit properties.

Import the custom Monaco Theme

Create inside the editor component where you have the <Editor />, a function to be executed before the editor starts (beforeMount):

import { Editor, type Monaco } from '@monaco-editor/react';
import OneDarkPro from './theme/onedarkpro.json';

const MyMonacoEditor = () => {
  const handleEditorDidMount = (monaco: Monaco) => {
    monaco.editor.defineTheme('OneDarkPro', {
      base: 'vs-dark',
      inherit: true,
      ...OneDarkPro
    });
  };

  return (
    <Editor width="100%" height="100vh" theme="OneDarkPro" beforeMount={handleEditorDidMount} />
  );
};

export default MyMonacoEditor;

Snippets

  • Add custom code font, font size, bracket pair colorization, word wrap, activate/disable minimap, cursor blinking, and format on paste:
<Editor
  options={{
    fontSize: 14,
    fontFamily: 'Jetbrains-Mono',
    fontLigatures: true,
    wordWrap: 'on',
    minimap: {
      enabled: false
    },
    bracketPairColorization: {
      enabled: true
    },
    cursorBlinking: 'expand',
    formatOnPaste: true,
    suggest: {
      showFields: false,
      showFunctions: false
    }
  }}
/>
  • Disable TypeScript checking in the editor:
const handleEditorDidMount = (monaco: Monaco) => {
  monaco.editor.defineTheme('OneDarkPro', {
    base: 'vs-dark',
    inherit: true,
    ...OneDarkPro
  });
  // 👇
  monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
    noSemanticValidation: true,
    noSyntaxValidation: true
  });
};
  • Add tsx (React + Typescript) support:
const handleEditorDidMount = (monaco: Monaco) => {
  monaco.editor.defineTheme('OneDarkPro', {
    base: 'vs-dark',
    inherit: true,
    ...OneDarkPro
  });
  // 👇
  monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
    tsx: 'react'
  });
};

✨ Building amazing things

Pablo Hernández

-

2024