Styling CodeMirror v6 with Material UI

Creating a uniform style and colour palette

In the last post I wrapped CodeMirror v6 with a react component. However, it still looked like a plain <textarea> when it should be looking like a code editor.

CodeMirror’s base setup has a grocery store’s worth of extensions to get started with full-fledged code editor. I have a much humbler objective, so I picked out the two extensions that I thought would be applicable to my use case:

  • @codemirror/highlight
  • @codemirror/matchbrackets

CodeMirror on its own is oblivious to code syntax and requires a set of rules to label segments of code. Fortunately, the @codemirror/lang-javascript extension contains the rules for tagging JavaScript/JSX and TypeScript/TSX.

I created a new file ~/components/editor/extensions.ts and import the relevant extensions. Most extensions will be the returned value of a function call. Some, like defaultHighlightStyle.fallback, will be values.

The EditorState.create configuration object in ~/components/editor/index.ts can then be updated with the extensions.

Going back to the site, the once dull text box now resembles a code editor.

Linking to Material UI

Having a unified colour palette for the site and the code editor seems like a reasonable requirement. Material UI’s theme has plenty of colours that I could pick from.

CodeMirror 6 has a straightforward way of modifying the highlight style.

In @codemirror/lang-javascript, I can see which tags are in use. With some regex magic I was able to rearrange the tags into a Map. As tedious as it is, I’ll need to map a colour to each tag.

In retrospect, I would choose a better way of organizing tagColorMap. Perhaps, putting the key as the style object and the value being an Array of tags that match that style.

I’ll need to convert the tagColorMap to the array of TagStyle objects that HighlightStyle.define requires.

In ~/components/editor/extensions.ts I’ll import highlightStyle and add it to the exported extensions.

Line Wrapping and Gutter Numbering

I noticed that long lines were pushing the output box off the screen. To enable line wrapping, EditorView.linewrapping needs to be added to the extensions.

Originally, I thought gutter numbering wouldn’t look good, but I changed my mind. All that’s needed is the @codemirror/gutter library.

Turning on Dark Mode

Using EditorView.theme and setting the second object to { dark: true }, will enable compatibility with dark themes. Most noticeably, the gutter numbers and the cursor become lighter.

After all the changes, this is what the code editor looks like:

TL; DR

Added custom styling to CodeMirror v6 using CodeMirror extensions and Material UI’s theme object.

This is just for the thumbnail

--

--

𝐁𝐚𝐲𝐚𝐧 𝐁𝐞𝐧𝐧𝐞𝐭𝐭
CodeX

My goal is to serve humanity and to bring happiness to others. I want to understand the problems around us and help find solutions. https://www.bayanbennett.com