nteract elements

CodeMirror Editor

A CodeMirror 6 editor component for notebook cells with syntax highlighting and language support.

The CodeMirrorEditor component provides a full-featured code editor built on CodeMirror 6. It includes syntax highlighting, key bindings, and support for multiple languages out of the box.

Try the editor above — switch languages, edit the code, and toggle between light/dark mode to see the theme adapt.

Installation

npx shadcn@latest add @nteract/codemirror-editor

New to @nteract? pnpm dlx shadcn@latest registry add @nteract

Install dependencies:

npm install @codemirror/view @codemirror/state @codemirror/commands @codemirror/autocomplete @codemirror/language @codemirror/lint @codemirror/lang-python @codemirror/lang-markdown @codemirror/lang-sql @codemirror/lang-html @codemirror/lang-javascript @codemirror/lang-json @uiw/react-codemirror

Then copy the files from registry/editor.

Usage

import { CodeMirrorEditor } from "@/components/editor";

export function MyCell() {
  const [source, setSource] = useState("print('Hello, world!')");

  return (
    <CodeMirrorEditor
      value={source}
      language="python"
      onValueChange={setSource}
      placeholder="Enter code..."
    />
  );
}

Supported Languages

LanguageValue
Python"python"
Markdown"markdown"
SQL"sql"
HTML"html"
JavaScript"javascript"
TypeScript"typescript"
JSON"json"
Plain Text"plain"

Props

PropTypeDefaultDescription
valuestringCurrent editor content
languageSupportedLanguage"python"Language for syntax highlighting
onValueChange(value: string) => voidCallback when content changes
autoFocusbooleanfalseAuto-focus on mount
onFocus() => voidCallback when editor gains focus
onBlur() => voidCallback when editor loses focus
placeholderstringPlaceholder text when empty
keyMapKeyBinding[]Additional key bindings
classNamestringAdditional CSS classes
maxHeightstringMaximum height (CSS value)
lineWrappingbooleanfalseEnable line wrapping
extensionsExtension[]Additional CodeMirror extensions
baseExtensionsExtension[]defaultExtensionsReplace default extensions
readOnlybooleanfalseRead-only mode
theme"light" | "dark" | "system""system"Theme mode

Themes

The editor includes GitHub Light and GitHub Dark themes that automatically adapt to your site's dark mode.

Automatic (Default)

By default (theme="system"), the editor detects dark mode from:

  1. Document class (.dark on <html>) - for site-level toggles
  2. data-theme="dark" attribute - another common pattern
  3. System preference (prefers-color-scheme: dark)
// Automatically adapts to dark mode
<CodeMirrorEditor
  value={source}
  language="python"
  onValueChange={setSource}
/>

Manual Control

Force a specific theme:

// Always light
<CodeMirrorEditor theme="light" ... />

// Always dark
<CodeMirrorEditor theme="dark" ... />

Theme Comparison

Light Theme
Dark Theme

Theme Utilities

Access theme utilities directly:

import { lightTheme, darkTheme, isDarkMode } from "@/components/editor";

// Check current dark mode state
if (isDarkMode()) {
  console.log("Dark mode is active");
}

// Use themes as extensions
<CodeMirrorEditor
  extensions={[isDarkMode() ? darkTheme : lightTheme]}
  ...
/>

Ref Methods

The component exposes methods via ref:

const editorRef = useRef<CodeMirrorEditorRef>(null);

// Focus the editor
editorRef.current?.focus();

// Move cursor to start or end
editorRef.current?.setCursorPosition("end");

// Access the underlying EditorView
const view = editorRef.current?.getEditor();

Custom Key Bindings

Add notebook-specific key bindings:

import { KeyBinding } from "@codemirror/view";

const notebookKeymap: KeyBinding[] = [
  {
    key: "Shift-Enter",
    run: () => {
      executeCell();
      return true;
    },
  },
  {
    key: "Mod-Enter",
    run: () => {
      executeCell();
      focusNextCell();
      return true;
    },
  },
];

<CodeMirrorEditor
  value={source}
  language="python"
  onValueChange={setSource}
  keyMap={notebookKeymap}
/>

Custom Extensions

Add themes or other CodeMirror extensions:

import { oneDark } from "@codemirror/theme-one-dark";
import { lineNumbers } from "@codemirror/view";

<CodeMirrorEditor
  value={source}
  language="python"
  onValueChange={setSource}
  extensions={[oneDark, lineNumbers()]}
/>

Minimal Setup (No Autocomplete)

For AI prompt inputs or simpler use cases:

import { minimalExtensions } from "@/components/editor";

<CodeMirrorEditor
  value={prompt}
  language="markdown"
  onValueChange={setPrompt}
  baseExtensions={minimalExtensions}
  lineWrapping
  placeholder="Describe what you want..."
/>

Language Detection

Detect language from filename:

import { detectLanguage } from "@/components/editor";

const language = detectLanguage("script.py"); // "python"
const language = detectLanguage("README.md"); // "markdown"

Integration with CellContainer

Combine with cell components for a complete notebook cell:

import { CellContainer } from "@/components/cell/CellContainer";
import { CellHeader } from "@/components/cell/CellHeader";
import { PlayButton } from "@/components/cell/PlayButton";
import { CodeMirrorEditor } from "@/components/editor";
import { OutputArea } from "@/components/cell/OutputArea";

function CodeCell({ cell, outputs }) {
  const [source, setSource] = useState(cell.source);
  
  return (
    <CellContainer cellId={cell.id}>
      <CellHeader
        leftContent={
          <PlayButton
            executionState={cell.state}
            cellType="code"
            onExecute={handleExecute}
            onInterrupt={handleInterrupt}
          />
        }
      />
      <CodeMirrorEditor
        value={source}
        language="python"
        onValueChange={setSource}
        keyMap={cellKeymap}
      />
      <OutputArea outputs={outputs} />
    </CellContainer>
  );
}

Bundled Themes

ThemePackageDescription
GitHub Light@uiw/codemirror-theme-githubClean light theme (default light)
GitHub Dark@uiw/codemirror-theme-githubDark theme matching GitHub (default dark)

To use other themes, install them and pass as extensions:

import { oneDark } from "@codemirror/theme-one-dark";

<CodeMirrorEditor
  theme="light" // Disable built-in theme
  extensions={[oneDark]}
  ...
/>

On this page