CodeEditor renders a Monaco editor that follows the Twenty theme in light and dark mode. CodeEditorHeader adds a bar above it for a title, tabs, or actions. Both come from twenty-ui/components/code-editor, a separate entry point, so the rest of Twenty UI works without Monaco.
Usage
Setup
Install the editor’s optional peer dependencies:monaco-editor package rather than a copy from a CDN. Monaco runs language features such as validation and autocompletion in web workers, and creating those workers depends on your bundler. Before an editor mounts, define MonacoEnvironment.getWorker as described in Monaco’s ESM integration guide. Without it, the editor still renders, but language features are unavailable.
The code editor does not run inside front components yet.
Controlled content
CodeEditorProps includes the installed Monaco React editor contract. onChange(value, event) receives the content (string | undefined) and the original IModelContentChangedEvent, including changed ranges, version and undo/redo details. Guard an undefined value at the boundary where your application requires a string.
beforeMount(monaco) runs after the Twenty theme is defined and before editor creation. onMount(editor, monaco) receives the editor instance after the selected theme is applied. onValidate(markers) receives Monaco diagnostics unchanged. overrideServices passes through to editor creation.
A Twenty Loader shows until Monaco loads. Pass loading to customize that content, or set isLoading to keep it visible while your own data loads. isLoading unmounts an existing editor and follows Monaco React’s model disposal rules.
Models and values
UsedefaultValue, defaultLanguage and defaultPath to initialize an uncontrolled model, or value, language and path for updates. These props retain Monaco React’s behavior, including its rules for choosing initial values and reusing an existing model URI. Changing defaultValue does not overwrite a model that already exists.
Changing path selects or creates a model. saveViewState defaults to true and restores the model’s cursor and scroll state when switching back. line reveals a line when the editor mounts or the prop changes. keepCurrentModel defaults to false; when true, the caller owns disposal of the retained model.
Native integration
ref points to the outer Twenty group div, which uses display: contents by default. This keeps the Monaco section in the parent’s sizing and flex layout. The outer div has no measurable layout box.
Use containerProps for the outer div’s native attributes, event handlers, class and style. Background, border, padding and dimensions require overriding its display. Prefer Monaco React’s wrapperProps section for layout styles and a measurable native ref. className targets the editor-container div inside that section; use onMount for the Monaco editor instance.
The Monaco React section contains its own loading content until the editor is ready. During initial bundled Monaco configuration or isLoading, Twenty renders a separate loader without wrapperProps or className. The outer containerProps and ref remain available in these states.
Add a header
variant="with-header" removes the editor’s top border so it joins the header. Use borderless when the editor sits inside a surface that already has a border.
The header accepts node content in title, startElement, and endElement. Use fragments for multiple tabs or actions. Native props, className, style, and ref target its root div. Use render to replace that root, for example render={<header />}. The title prop supplies visible content; to set a native title attribute, pass it on the element supplied to render.
Size and appearance
The editor is 450px tall and 100% wide by default.width and height accept pixels or a CSS length.
Sizing follows this order:
resizablestarts from the rendered height, including CSS lengths, within the resize handle’s 50px to 500px bounds. It adds a handle after Monaco mounts. Dragging or keyboard input then sets a pixel height. Changingheightresets it within the same bounds.- Otherwise,
autoHeightuses Monaco’s content height. The explicit or default height is used until content is measured. - Otherwise, the explicit or default
heightapplies.
automaticLayout by default. If you disable it in options, your application must call editor.layout() when the container changes size. Native wrapperProps.style is passed unchanged and can override the section’s width or height.
Pass a localized resizeLabel to name the resize handle for screen readers.
Twenty supplies font, formatting, scrollbar, minimap and padding defaults. contentPadding="comfortable" also widens the gap between line numbers and code. Caller options replace the corresponding defaults, including the whole padding object and lineDecorationsWidth.
An explicit theme takes precedence over options.theme; otherwise the editor follows Twenty’s light or dark theme. Define custom Monaco themes in beforeMount. Monaco themes are global, so changing one affects other Monaco editors on the same page. transparentBackground controls the Twenty wrapper appearance independently.
Validation
Monaco reports its own diagnostics, such as JSON syntax errors, throughonValidate. To add your own, return marker data from setMarkers. It runs on mount, model selection and every model content change, including controlled value updates, and replaces the custom markers for the current model.
Keyboard
While the editor has focus, it stops keyboard events from propagating. React key handlers on parent components and document-level shortcuts do not receive keystrokes typed in the editor.Props
CodeEditor
boolean
default:"false"
Grows the editor to fit its content instead of using
height. Ignored when resizable is set.BeforeMount
Called with Monaco before editor creation, after the Twenty theme has been defined. Use it to register custom themes or languages.
string
Class applied to the Monaco editor-container div.
Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, "children">
Native props, className and style for the outer Twenty group div. Its default
display: contents preserves the Monaco section’s parent sizing and flex layout without creating a layout box. Background, border, padding and dimensions require overriding display. Prefer wrapperProps for section layout styles. Its keyboard handler runs before focused editor keystrokes stop propagating."comfortable" | "default"
default:"default"
default supplies top and bottom padding. comfortable also widens the gap between line numbers and code. Explicit Monaco options override these defaults.string
Initial Monaco language for a newly created model.
string
Initial model URI, used when
path is omitted.string
Initial content for a model created by Monaco React.
string | number
default:"450"
Editor height in pixels or as a CSS length, defaulting to 450px. Resizing starts from this rendered height and resets when this prop changes. Auto-height uses it until content is measured.
boolean
default:"false"
Shows a loader at the editor height instead of the editor. A loader also shows while Monaco loads.
boolean
default:"false"
Keeps the current model when the editor unmounts. Defaults to false. The caller owns disposal of retained models.
string
Monaco language identifier for highlighting and language services, such as
json or typescript.number
Line revealed when the editor mounts or this prop changes.
ReactNode
default:"<Loader />"
Content shown while Monaco loads or
isLoading is true. Defaults to the Twenty Loader.OnChange
Monaco React callback with the full content (string or undefined) and the original IModelContentChangedEvent.
OnMount
Called when the editor is ready, with the editor instance and the Monaco namespace. The selected theme is already applied.
OnValidate
Called with the markers Monaco reports after validating the content, such as JSON syntax errors.
IStandaloneEditorConstructionOptions
Monaco editor options merged over Twenty defaults. Explicit values, including padding, replace the corresponding defaults. The
theme prop takes precedence over options.theme.IEditorOverrideServices
Monaco services passed through when the editor is created.
string
URI of the current model. Changing it selects or creates a model using Monaco React behavior.
Ref<HTMLDivElement>
Ref to the outer Twenty group div, which has no measurable layout box with its default
display: contents. Use wrapperProps for a measurable section ref or onMount for the Monaco editor instance.boolean
default:"false"
Adds a height resize handle after Monaco mounts, bounded from 50px to 500px. Takes precedence over autoHeight. A changed height prop resets the resized height within these bounds.
string
default:"Resize editor"
Accessible name of the resize handle. Pass a localized label when
resizable is enabled.boolean
default:"true"
Preserves Monaco React view state between model changes. Defaults to true.
((value: string) => IMarkerData[])
Returns custom validation markers for the current model content. Runs on mount, model selection and content changes, including controlled updates.
string
default:"Twenty theme"
Monaco theme name. Takes precedence over
options.theme, which takes precedence over the Twenty theme. Define custom themes in beforeMount.boolean
Removes the editor background so the surrounding surface shows through.
string
Content of the editor. Pair it with
onChange to control the editor."borderless" | "default" | "with-header"
default:"default"
Border treatment:
default draws a rounded border, with-header attaches the editor below a CodeEditorHeader, and borderless removes the border.string | number
default:"100%"
Width of the Monaco React section, in pixels or as a CSS length.
object
Native props passed unchanged to the Monaco React section around the editor and Monaco React loading content. Use this section for layout styles and a measurable native ref. Not applied to the separate Twenty loader during initial Monaco configuration or
isLoading. Native styles can override the section sizing.CodeEditorHeader
string
Additional CSS class applied to the root element.
ReactNode
Content shown at the end of the header, such as actions. Use a fragment for multiple elements.
Ref<HTMLDivElement>
Ref forwarded to the rendered root element, a div by default.
ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, {}>
Replace the root div or compose it with another component. Native props and refs target the rendered root.
ReactNode
Content shown at the start of the header, before the title, such as tabs. Use a fragment for multiple elements.
CSSProperties
Inline styles applied to the root element.
ReactNode
Content shown after
startElement. This is visible header content, not the native HTML title attribute.