# How to Embed Excalidraw Drawings in the React TipTap Editor: A Complete Implementation Guide

> Learn how to embed Excalidraw drawings in your React TipTap editor with this guide. The dedicated extension renders static SVG previews and offers an interactive editing canvas.

- Repository: [Hung Hoang/reactjs-tiptap-editor](https://github.com/hunghg255/reactjs-tiptap-editor)
- Tags: how-to-guide
- Published: 2026-03-03

---

**The reactjs-tiptap-editor library ships with a dedicated Excalidraw extension that treats each drawing as a block-level node, rendering static SVG previews in the document and providing an interactive canvas for editing.**

Embedding Excalidraw drawings directly into rich-text content requires specialized handling for both data storage and rendering. The `hunghg255/reactjs-tiptap-editor` repository provides a complete solution by implementing a custom TipTap node that stores Excalidraw JSON data and renders it as scalable vector graphics. This architecture cleanly separates the heavy interactive editor from lightweight preview rendering, ensuring optimal performance while maintaining full drawing capabilities.

## Extension Architecture and Core Components

The Excalidraw integration follows a three-layer architecture: node definition, view rendering, and user interface controls.

### Node Definition in Excalidraw.ts

At [`src/extensions/Excalidraw/Excalidraw.ts`](https://github.com/hunghg255/reactjs-tiptap-editor/blob/main/src/extensions/Excalidraw/Excalidraw.ts), the extension registers a TipTap `Node` named **excalidraw**. This declaration specifies three critical attributes:

- `width` – Controls the display width of the embedded drawing
- `height` – Defines the vertical dimensions
- `data` – Stores the complete Excalidraw JSON serialization

The file also exposes the **`setExcalidraw`** command, which either updates an existing node or inserts a new one at the current cursor position. According to the source code, this command accepts an object containing the drawing data and optional dimension parameters.

### SVG Preview Rendering with NodeViewExcalidraw

The [`NodeViewExcalidraw.tsx`](https://github.com/hunghg255/reactjs-tiptap-editor/blob/main/NodeViewExcalidraw.tsx) component handles how drawings appear within the document. It lazily imports the **`exportToSvg`** helper from the Excalidraw package to convert the stored JSON into a static SVG representation. This approach avoids loading the full Excalidraw library during initial page render, significantly improving bundle size and load times.

The component wraps the SVG in a resizable container, allowing users to adjust dimensions directly within the editor interface. When the node is selected, resize handles appear, modifying the `width` and `height` attributes stored in the document model.

### Rich-Text Interface Components

Two React components provide the user interface for creating and editing drawings:

**RichTextExcalidraw.tsx** – Located at [`src/extensions/Excalidraw/components/RichTextExcalidraw.tsx`](https://github.com/hunghg255/reactjs-tiptap-editor/blob/main/src/extensions/Excalidraw/components/RichTextExcalidraw.tsx), this toolbar button opens a modal dialog containing the full `@excalidraw/excalidraw` canvas. The component dynamically imports the heavy drawing library only when the user clicks the button. Upon saving, it executes `editor.chain().focus().setExcalidraw({ data })` to embed the drawing.

**RichTextBubbleExcalidraw.tsx** – Found at [`src/components/Bubble/RichTextBubbleExcalidraw.tsx`](https://github.com/hunghg255/reactjs-tiptap-editor/blob/main/src/components/Bubble/RichTextBubbleExcalidraw.tsx), this bubble menu appears when selecting an existing drawing node. It provides quick actions for size adjustment, deletion, and toggling the drawing picker without accessing the main toolbar.

## Implementing the Excalidraw Extension

To embed Excalidraw drawings in your React TipTap editor, you must register the extension, add the toolbar control, and render the editor instance.

### Register the Extension

Import the `Excalidraw` node from the package and include it in your extensions array:

```tsx
import { Excalidraw } from 'reactjs-tiptap-editor/excalidraw';
import { Document, Text, Paragraph } from '@tiptap/extension-document';
import { useEditor } from '@tiptap/react';

const extensions = [
  Document,
  Text,
  Paragraph,
  // ...other core extensions
  Excalidraw,                 // ← register the node
];

const editor = useEditor({ extensions });

```

### Add the Toolbar Button

Include the `RichTextExcalidraw` component in your toolbar to provide the drawing interface:

```tsx
import { RichTextExcalidraw } from 'reactjs-tiptap-editor/excalidraw';

const RichTextToolbar = () => (
  <>
    {/* other toolbar buttons */}
    <RichTextExcalidraw />   {/* opens the Excalidraw modal */}
  </>
);

```

### Complete Editor Setup

Wrap your components with the `RichTextProvider` and render the editable area:

```tsx
import { RichTextProvider, EditorContent } from 'reactjs-tiptap-editor';

export const App = () => {
  const editor = useEditor({ 
    extensions: [
      Document,
      Text,
      Paragraph,
      Excalidraw,
      // ...other extensions
    ] 
  });

  return (
    <RichTextProvider editor={editor}>
      <RichTextToolbar />
      <EditorContent editor={editor} />
    </RichTextProvider>
  );
};

```

## Programmatic Drawing Insertion

Beyond the UI controls, you can programmatically embed Excalidraw drawings using the `setExcalidraw` command.

### Basic Programmatic Insertion

Invoke the command chain to insert a drawing at the current cursor position:

```tsx
// `drawingData` must be the JSON format produced by Excalidraw
editor
  .chain()
  .focus()
  .setExcalidraw({ data: drawingData, width: '100%', height: 300 })
  .run();

```

### Handling External Events

The repository demonstrates advanced integration patterns in [`playground/src/App.tsx`](https://github.com/hunghg255/reactjs-tiptap-editor/blob/main/playground/src/App.tsx), where drawings can be inserted in response to external events. Using the custom event bus, you can listen for Excalidraw data from outside the editor:

```tsx
import { EVENTS } from '@/utils/customEvents/events.constant';
import { useListener } from '@/components/ReactBus';
import { useEditorInstance } from '@/store/editor';

const editor = useEditorInstance();
const EVENT_ID = EVENTS.EXCALIDRAW((editor as any).id);

useListener((payload) => {
  // `payload.data` is the Excalidraw JSON
  editor.chain().focus().setExcalidraw({ data: payload.data }).run();
}, [EVENT_ID]);

```

This pattern enables integrations with file dropzones, external drawing managers, or collaborative editing systems.

## Summary

- **Excalidraw Node Definition**: The extension at [`src/extensions/Excalidraw/Excalidraw.ts`](https://github.com/hunghg255/reactjs-tiptap-editor/blob/main/src/extensions/Excalidraw/Excalidraw.ts) defines a block-level node with `width`, `height`, and `data` attributes, plus the `setExcalidraw` command for insertion.
- **Performance-Optimized Rendering**: [`NodeViewExcalidraw.tsx`](https://github.com/hunghg255/reactjs-tiptap-editor/blob/main/NodeViewExcalidraw.tsx) renders drawings as SVGs using lazy-loaded `exportToSvg`, keeping the initial bundle size small while supporting resizable previews.
- **Interactive Editing**: [`RichTextExcalidraw.tsx`](https://github.com/hunghg255/reactjs-tiptap-editor/blob/main/RichTextExcalidraw.tsx) dynamically imports the full Excalidraw canvas only when needed, embedding results via the `setExcalidraw` command chain.
- **Contextual Controls**: [`RichTextBubbleExcalidraw.tsx`](https://github.com/hunghg255/reactjs-tiptap-editor/blob/main/RichTextBubbleExcalidraw.tsx) provides bubble-menu actions for quick adjustments to existing drawings.
- **Programmatic API**: The `setExcalidraw` command supports both manual insertion and event-driven workflows, accepting drawing JSON and dimension parameters.

## Frequently Asked Questions

### How do I install the Excalidraw extension for reactjs-tiptap-editor?

The Excalidraw extension ships as part of the main `reactjs-tiptap-editor` package. Import it from the `reactjs-tiptap-editor/excalidraw` subpath and add it to your TipTap extensions array. The heavy `@excalidraw/excalidraw` dependency is loaded on-demand only when users open the drawing modal, so it won't bloat your initial JavaScript bundle.

### What data format does the Excalidraw extension store in the document?

The extension stores the native Excalidraw JSON serialization in the `data` attribute of the node. This is the same format produced by Excalidraw's serialization methods, containing all scene elements, app state, and binding information. The `width` and `height` attributes store display dimensions separately, allowing you to resize the visual representation without modifying the underlying drawing data.

### Can I edit an existing Excalidraw drawing after embedding it?

Yes. When you select an embedded drawing in the editor, the bubble menu provided by [`RichTextBubbleExcalidraw.tsx`](https://github.com/hunghg255/reactjs-tiptap-editor/blob/main/RichTextBubbleExcalidraw.tsx) offers an edit action that reopens the full Excalidraw canvas with the existing `data` loaded. You can modify the diagram and save changes back to the document using the same `setExcalidraw` command, which updates the node in place.

### How do I set default dimensions for all embedded Excalidraw drawings?

Pass `width` and `height` parameters when calling `setExcalidraw` programmatically, or modify the default attribute values in the node configuration when initializing the editor. The SVG preview container respects these attributes for initial rendering, though users can still resize individual drawings via the drag handles provided by [`NodeViewExcalidraw.tsx`](https://github.com/hunghg255/reactjs-tiptap-editor/blob/main/NodeViewExcalidraw.tsx) unless you disable the resizable node view.