> ## Documentation Index
> Fetch the complete documentation index at: https://docs.twenty.com/llms.txt
> Use this file to discover all available pages before exploring further.

# CodeEditor

> Edit and display code in a Monaco editor styled with the Twenty theme.

`CodeEditor` renders a [Monaco](https://microsoft.github.io/monaco-editor/) 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.

**Light**

[Code editor example (light)](https://storybook.twenty.com/iframe.html?id=ui-components-codeeditor--display\&viewMode=story\&globals=colorScheme:light)

**Dark**

[Code editor example (dark)](https://storybook.twenty.com/iframe.html?id=ui-components-codeeditor--display\&viewMode=story\&globals=colorScheme:dark)

[Open in Storybook](https://storybook.twenty.com/?path=/story/ui-components-codeeditor--display)

## Usage

```tsx theme={null}
import { CodeEditor, CodeEditorHeader } from 'twenty-ui/components/code-editor';

export const WorkspaceEditor = () => (
  <>
    <CodeEditorHeader title="workspace.json" />
    <CodeEditor
      variant="with-header"
      language="json"
      defaultValue={JSON.stringify(
        { name: 'Acme', plan: 'Pro', seats: 12 },
        null,
        2,
      )}
      height={160}
    />
  </>
);
```

## Setup

Install the editor's optional peer dependencies:

```bash theme={null}
yarn add @monaco-editor/react monaco-editor
```

The editor loads your installed `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](https://github.com/microsoft/monaco-editor/blob/main/docs/integrate-esm.md). Without it, the editor still renders, but language features are unavailable.

The code editor does not run inside [front components](/developers/extend/apps/layout/front-components.md) yet.

## Controlled content

```tsx theme={null}
import { useState } from 'react';
import { isDefined } from 'twenty-ui/utilities';
import { CodeEditor } from 'twenty-ui/components/code-editor';

export const PayloadEditor = () => {
  const [payload, setPayload] = useState('{\n  "name": "Acme"\n}');

  return (
    <CodeEditor
      language="json"
      value={payload}
      onChange={(value) => {
        if (isDefined(value)) {
          setPayload(value);
        }
      }}
      height={200}
    />
  );
};
```

`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

Use `defaultValue`, `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.

```tsx theme={null}
import { CodeEditor } from 'twenty-ui/components/code-editor';

export const FileEditor = () => (
  <CodeEditor
    defaultPath="file:///workspace/settings.json"
    defaultLanguage="json"
    defaultValue={'{\n  "name": "Acme"\n}'}
    saveViewState
  />
);
```

## 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.

```tsx theme={null}
import { useRef } from 'react';
import { CodeEditor } from 'twenty-ui/components/code-editor';

export const NamedEditor = () => {
  const containerRef = useRef<HTMLDivElement>(null);

  return (
    <CodeEditor
      ref={containerRef}
      containerProps={{ id: 'payload-editor' }}
      wrapperProps={{ 'data-editor-surface': 'payload' }}
      options={{ ariaLabel: 'Payload code' }}
    />
  );
};
```

## Add a header

```tsx theme={null}
import { CodeEditor, CodeEditorHeader } from 'twenty-ui/components/code-editor';
import { Button } from 'twenty-ui/primitives/input';

type ScriptEditorProps = {
  script: string;
  onRun: () => void;
};

export const ScriptEditor = ({ script, onRun }: ScriptEditorProps) => (
  <div>
    <CodeEditorHeader
      title="index.ts"
      endElement={
        <Button size="sm" onClick={onRun}>
          Run
        </Button>
      }
    />
    <CodeEditor language="typescript" value={script} variant="with-header" />
  </div>
);
```

`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:

1. `resizable` starts 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. Changing `height` resets it within the same bounds.
2. Otherwise, `autoHeight` uses Monaco's content height. The explicit or default height is used until content is measured.
3. Otherwise, the explicit or default `height` applies.

Monaco React enables `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, through `onValidate`. 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

**autoHeight** `boolean` (default: false)

Grows the editor to fit its content instead of using `height`. Ignored when `resizable` is set.

**beforeMount** `BeforeMount`

Called with Monaco before editor creation, after the Twenty theme has been defined. Use it to register custom themes or languages.

**className** `string`

Class applied to the Monaco editor-container div.

**containerProps** `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.

**contentPadding** `"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.

**defaultLanguage** `string`

Initial Monaco language for a newly created model.

**defaultPath** `string`

Initial model URI, used when `path` is omitted.

**defaultValue** `string`

Initial content for a model created by Monaco React.

**height** `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.

**isLoading** `boolean` (default: false)

Shows a loader at the editor height instead of the editor. A loader also shows while Monaco loads.

**keepCurrentModel** `boolean` (default: false)

Keeps the current model when the editor unmounts. Defaults to false. The caller owns disposal of retained models.

**language** `string`

Monaco language identifier for highlighting and language services, such as `json` or `typescript`.

**line** `number`

Line revealed when the editor mounts or this prop changes.

**loading** `ReactNode` (default: \<Loader />)

Content shown while Monaco loads or `isLoading` is true. Defaults to the Twenty Loader.

**onChange** `OnChange`

Monaco React callback with the full content (string or undefined) and the original IModelContentChangedEvent.

**onMount** `OnMount`

Called when the editor is ready, with the editor instance and the Monaco namespace. The selected theme is already applied.

**onValidate** `OnValidate`

Called with the markers Monaco reports after validating the content, such as JSON syntax errors.

**options** `IStandaloneEditorConstructionOptions`

Monaco editor options merged over Twenty defaults. Explicit values, including padding, replace the corresponding defaults. The `theme` prop takes precedence over `options.theme`.

**overrideServices** `IEditorOverrideServices`

Monaco services passed through when the editor is created.

**path** `string`

URI of the current model. Changing it selects or creates a model using Monaco React behavior.

**ref** `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.

**resizable** `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.

**resizeLabel** `string` (default: Resize editor)

Accessible name of the resize handle. Pass a localized label when `resizable` is enabled.

**saveViewState** `boolean` (default: true)

Preserves Monaco React view state between model changes. Defaults to true.

**setMarkers** `((value: string) =\> IMarkerData[])`

Returns custom validation markers for the current model content. Runs on mount, model selection and content changes, including controlled updates.

**theme** `string` (default: Twenty theme)

Monaco theme name. Takes precedence over `options.theme`, which takes precedence over the Twenty theme. Define custom themes in `beforeMount`.

**transparentBackground** `boolean`

Removes the editor background so the surrounding surface shows through.

**value** `string`

Content of the editor. Pair it with `onChange` to control the editor.

**variant** `"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.

**width** `string | number` (default: 100%)

Width of the Monaco React section, in pixels or as a CSS length.

**wrapperProps** `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

**className** `string`

Additional CSS class applied to the root element.

**endElement** `ReactNode`

Content shown at the end of the header, such as actions. Use a fragment for multiple elements.

**ref** `Ref\<HTMLDivElement\>`

Ref forwarded to the rendered root element, a div by default.

**render** `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.

**startElement** `ReactNode`

Content shown at the start of the header, before the title, such as tabs. Use a fragment for multiple elements.

**style** `CSSProperties`

Inline styles applied to the root element.

**title** `ReactNode`

Content shown after `startElement`. This is visible header content, not the native HTML title attribute.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.