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

# EmailEditor

> Standalone editor component with built-in menus, slash commands, and export helpers.

`EmailEditor` is the highest-level way to embed the React Email editor. It wraps
Tiptap's `EditorProvider`, mounts the default editor UI, and exposes a ref API
for exporting HTML, plain text, and JSON.

Use it when you want a batteries-included editor. If you need full control over
the provider, overlays, or extension list, compose the editor from the lower-level
APIs instead.

> [!TIP]
>
> `EmailEditor` works out of the box, but ships unstyled. To style the default
> bubble menus, slash command menu, and inspector, import the default theme
> separately:
>
> ```tsx theme={"theme":{"light":"github-light","dark":"vesper"}}
> import '@react-email/editor/themes/default.css';
> ```
>
> See [styling](https://react.email/docs/editor/features/styling.md) for details on customizing the editor's appearance.

## Import

```tsx theme={"theme":{"light":"github-light","dark":"vesper"}}
import '@react-email/editor/themes/default.css';
import { EmailEditor, type EmailEditorRef } from '@react-email/editor';
```

## Signature

```tsx theme={"theme":{"light":"github-light","dark":"vesper"}}
const EmailEditor: React.ForwardRefExoticComponent<
  EmailEditorProps & React.RefAttributes<EmailEditorRef>
>;
```

## Default behavior

When rendered without a custom `extensions` prop, `EmailEditor` configures:

* [`StarterKit`](https://react.email/docs/editor/api-reference/extensions-list)
* `Placeholder`
* [`EmailTheming`](https://react.email/docs/editor/api-reference/theming-api)
* The default text `BubbleMenu`
* [`BubbleMenu.LinkDefault`](https://react.email/docs/editor/api-reference/ui/bubble-menu#bubblemenu-linkdefault)
* [`BubbleMenu.ButtonDefault`](https://react.email/docs/editor/api-reference/ui/bubble-menu#bubblemenu-buttondefault)
* [`BubbleMenu.ImageDefault`](https://react.email/docs/editor/api-reference/ui/bubble-menu#bubblemenu-imagedefault)
* The [built-in slash command menu](https://react.email/docs/editor/api-reference/ui/slash-command.md#default-commands)

If [`onUploadImage`](#onuploadimage) is provided, the image upload extension is
appended automatically.

## Props

**content** `Content`

Initial editor content. Accepts TipTap JSON or an HTML string.

**onUpdate** `(ref: EmailEditorRef) =\> void`

Called on every content update. The callback receives the same helper object
exposed through the component ref.

**onReady** `(ref: EmailEditorRef) =\> void`

Called once after the editor instance is mounted and ready.

**theme** `EditorThemeInput` (default: 'basic')

Built-in theme preset or custom theme object used by the default
`EmailTheming` extension.

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

Toggles read-only mode for the editor content.

**placeholder** `string`

Overrides the default placeholder text. When omitted, paragraphs show
`Press '/' for commands`.

**bubbleMenu** `\{ hideWhenActiveNodes?: string[]; hideWhenActiveMarks?: string[] \}`

Configures when the default text bubble menu should stay hidden.

**extensions** `Extensions`

Replaces the default extensions array. Use this when you want more control
over the editor schema or plugin list.

**onUploadImage** `(file: File) =\> Promise\<\{ url: string \}\>`

Enables image upload for paste, drop, and image insertion flows. Resolve with
the final hosted image URL. See [Image Upload](https://react.email/docs/editor/features/image-upload.md)
for setup patterns and [Image Upload API](https://react.email/docs/editor/api-reference/image-upload-api.md)
for the lower-level hook, commands, and types.

**className** `string`

Applied to the underlying editor container element.

**children** `ReactNode`

Additional UI rendered inside the internal `EditorProvider`. Children render
as siblings of the editor content area, which makes layouts like split-pane
editors and inspector sidebars work naturally.

### bubbleMenu options

**hideWhenActiveNodes** `string[]` (default: \['button'])

Prevents the default text bubble menu from appearing when one of these node
types is active.

**hideWhenActiveMarks** `string[]` (default: \['link'])

Prevents the default text bubble menu from appearing when one of these mark
types is active.

## Ref API

```tsx theme={"theme":{"light":"github-light","dark":"vesper"}}
interface EmailEditorRef {
  getEmail(): Promise<{ html: string; text: string }>;
  getEmailHTML(): Promise<string>;
  getEmailText(): Promise<string>;
  getJSON(): JSONContent;
  editor: Editor | null;
}
```

**getEmail** `() =\> Promise\<\{ html: string; text: string \}\>`

Serializes the current document to email-ready HTML and plain text in one
call.

**getEmailHTML** `() =\> Promise\<string\>`

Returns only the HTML export.

**getEmailText** `() =\> Promise\<string\>`

Returns only the plain text export.

**getJSON** `() =\> JSONContent`

Returns the current TipTap JSON document.

**editor** `Editor | null`

The underlying TipTap editor instance. `null` until the editor is ready.

> [!NOTE]
>
> Before the editor is ready, the export methods resolve to empty output and
> `getJSON()` returns an empty document with `type: 'doc'` and an empty
> `content` array.

## Example

```tsx theme={"theme":{"light":"github-light","dark":"vesper"}}
import '@react-email/editor/themes/default.css';
import { EmailEditor, type EmailEditorRef } from '@react-email/editor';
import { useRef, useState } from 'react';

export function MyEditor() {
  const editorRef = useRef<EmailEditorRef>(null);
  const [html, setHtml] = useState('');

  const handleExport = async () => {
    if (!editorRef.current) return;
    setHtml(await editorRef.current.getEmailHTML());
  };

  return (
    <div>
      <EmailEditor
        ref={editorRef}
        content="<h1>Welcome</h1><p>Edit this email.</p>"
        theme="basic"
        onReady={(ref) => {
          console.log(ref.getJSON());
        }}
        onUpdate={(ref) => {
          console.log(ref.editor?.isEmpty);
        }}
      />

      <button onClick={handleExport}>Export HTML</button>

      {html && <textarea readOnly value={html} rows={12} />}
    </div>
  );
}
```

## See also

* [Getting Started](https://react.email/docs/editor/getting-started.md)
* [BubbleMenu](https://react.email/docs/editor/api-reference/ui/bubble-menu.md)
* [Inspector](https://react.email/docs/editor/api-reference/ui/inspector.md)
* [composeReactEmail](https://react.email/docs/editor/api-reference/compose-react-email.md)
* [Theming API](https://react.email/docs/editor/api-reference/theming-api.md)
* [Image Upload API](https://react.email/docs/editor/api-reference/image-upload-api.md)


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