# How Draw.io Desktop Implements a Custom Context Menu with Paste and Match Style

> Discover how Draw.io Desktop implements a custom context menu with Paste and Match Style using electron-context-menu and webContents pasteAndMatchStyle for seamless formatting control.

- Repository: [draw.io/drawio-desktop](https://github.com/jgraph/drawio-desktop)
- Tags: internals
- Published: 2026-03-05

---

**Draw.io Desktop leverages the `electron-context-menu` library in [`src/main/electron.js`](https://github.com/jgraph/drawio-desktop/blob/main/src/main/electron.js) to inject a "Paste and Match Style" option that appears only when plain text exists on the clipboard, executing `browserWindow.webContents.pasteAndMatchStyle()` to strip formatting during paste operations.**

The jgraph/drawio-desktop application provides a native-like editing experience by customizing the right-click menu in its Electron-based interface. The implementation of the **custom context menu**, specifically the **"Paste and Match Style"** functionality, demonstrates how to extend default Electron menus with conditional logic and clipboard-aware visibility controls.

## Electron Context Menu Architecture

The application builds its menu system on top of the third-party `electron-context-menu` package, which automatically attaches to all renderer windows and provides hooks for custom extensions.

### Library Integration in the Main Process

In [`src/main/electron.js`](https://github.com/jgraph/drawio-desktop/blob/main/src/main/electron.js) (lines 16-17), the module imports the library alongside standard Electron APIs:

```javascript
import { clipboard, BrowserWindow } from 'electron';
import contextMenu from 'electron-context-menu';

```

### Configuring the Append Callback

The configuration occurs at lines 53-71 of [`src/main/electron.js`](https://github.com/jgraph/drawio-desktop/blob/main/src/main/electron.js), where the `contextMenu()` function receives an **append** callback. This callback injects the custom "Paste and Match Style" entry into the default menu array:

```javascript
contextMenu({
    showCopyImage: true,
    showSaveImage: true,
    showSaveImageAs: true,
    showLookUpSelection: false,
    showSearchWithGoogle: false,
    showCopyLink: false,
    showSelectAll: true,
    append: (defaultActions, params, browserWindow) => [
        {
            label: 'Paste and Match Style',
            visible: clipboard.availableFormats().includes('text/plain'),
            click: () => {
                browserWindow.webContents.pasteAndMatchStyle();
            }
        }
    ]
});

```

### Conditional Visibility and Execution Logic

The **visible** property dynamically controls menu item availability by checking `clipboard.availableFormats()` for the `'text/plain'` type. When the user clicks the option, the **click** handler invokes `browserWindow.webContents.pasteAndMatchStyle()`, an Electron API that inserts clipboard content without source formatting—effectively matching the destination style.

## Dependency and Project Structure

The `electron-context-menu` dependency is declared in [`package.json`](https://github.com/jgraph/drawio-desktop/blob/main/package.json) under the standard `dependencies` section. No native modules are required, as the implementation relies purely on Electron's built-in **clipboard** and **webContents** APIs.

While [`src/main/electron-preload.js`](https://github.com/jgraph/drawio-desktop/blob/main/src/main/electron-preload.js) establishes the secure IPC bridge for renderer communication, the context menu logic remains entirely within the main process, with menu actions directly manipulating web contents.

## Standalone Implementation Example

To replicate this pattern in a minimal Electron application:

```javascript
// main.js
import { app, BrowserWindow, clipboard } from 'electron';
import contextMenu from 'electron-context-menu';

function createWindow () {
  const win = new BrowserWindow({ 
    webPreferences: { nodeIntegration: false } 
  });
  win.loadURL('https://example.com');
}

app.whenReady().then(() => {
  contextMenu({
    showSelectAll: true,
    append: (defaultActions, params, browserWindow) => [{
      label: 'Paste and Match Style',
      visible: clipboard.availableFormats().includes('text/plain'),
      click: () => browserWindow.webContents.pasteAndMatchStyle()
    }]
  });

  createWindow();
});

```

## Extending with Additional Custom Actions

Developers can augment the menu array returned by the **append** function with multiple custom entries. Each object supports **label**, **visible**, **enabled**, and **click** properties, allowing complex conditional logic based on `params.selectionText` or other browser window attributes.

## Summary

- Draw.io Desktop uses `electron-context-menu` in [`src/main/electron.js`](https://github.com/jgraph/drawio-desktop/blob/main/src/main/electron.js) to customize the right-click experience
- The "Paste and Match Style" option appears only when `clipboard.availableFormats()` contains `'text/plain'`
- Execution calls `browserWindow.webContents.pasteAndMatchStyle()` to paste unformatted text
- Configuration spans lines 53-71, with library imports at lines 16-17
- The implementation requires no native code, relying solely on standard Electron APIs

## Frequently Asked Questions

### How does Draw.io detect when to show the "Paste and Match Style" option?

The menu item's **visible** property checks `clipboard.availableFormats().includes('text/plain')` to determine if plain text exists on the system clipboard. If no plain text is available, the option remains hidden from the context menu.

### What is the difference between standard paste and pasteAndMatchStyle?

Standard paste operations preserve source formatting from the clipboard, while `pasteAndMatchStyle()` strips all formatting and inserts the content using the destination's current text styles. This matches the behavior of "Paste and Match Style" commands in native macOS and Windows applications.

### Can I add other custom items to the Draw.io context menu?

Yes. The **append** callback in [`src/main/electron.js`](https://github.com/jgraph/drawio-desktop/blob/main/src/main/electron.js) returns an array of menu item objects. Developers can add additional entries with custom labels, visibility conditions based on `params.selectionText`, and click handlers that invoke `browserWindow.webContents` methods or IPC calls to the renderer process.

### Where is the electron-context-menu dependency declared?

The dependency is listed in [`package.json`](https://github.com/jgraph/drawio-desktop/blob/main/package.json) under the `dependencies` section, ensuring it installs automatically with the project. The library is then imported at line 16 of [`src/main/electron.js`](https://github.com/jgraph/drawio-desktop/blob/main/src/main/electron.js) and instantiated immediately after command-line option handling.