Skip to main content
Everything is accessed through a single import:

Pre-built menus

Drop-in menus for common use cases. Each one handles its own trigger logic and plugin key.

BubbleMenu.LinkDefault

Link editing menu that appears when clicking a link.
excludeItems
('edit-link' | 'open-link' | 'unlink')[]
default:"[]"
Actions to hide from the toolbar.
placement
'top' | 'bottom'
default:"'top'"
Position relative to the link.
offset
number
Distance from the link in pixels.
onHide
() => void
Called when the bubble menu is hidden.
validateUrl
(value: string) => string | null
Custom URL validator. Return the valid URL string or null.
Called after a link is applied.
Called after a link is removed.

BubbleMenu.ButtonDefault

Button link editing menu that appears when clicking a button.
Same props as LinkDefault (except excludeItems).

BubbleMenu.ImageDefault

Image editing menu that appears when clicking an image.
excludeItems
('edit-link' | 'unlink')[]
default:"[]"
Actions to hide from the toolbar.
placement
'top' | 'bottom'
default:"'top'"
Position relative to the image.
offset
number
Distance from the image in pixels.
onHide
() => void
Called when the bubble menu is hidden.
validateUrl
(value: string) => string | null
Custom URL validator. Return the valid URL string or null.
Called after a link is applied to the image.
Called after a link is removed from the image.

Combining menus

A typical email editor uses multiple bubble menus together. Use hideWhenActiveNodes and hideWhenActiveMarks to prevent overlapping menus:

Compound components

Build fully custom menus using the compound API.

BubbleMenu

Base container for all custom bubble menus. Provides editor context to children. When rendered without children, it automatically renders the default text formatting toolbar.
trigger
TriggerFn
Controls when the menu is visible. Defaults to showing on text selection. Use bubbleMenuTriggers for common patterns.
pluginKey
PluginKey
Unique key for the ProseMirror plugin backing this menu. Required when rendering multiple BubbleMenu instances to avoid collisions. Import PluginKey from @tiptap/pm/state.
hideWhenActiveNodes
string[]
default:"[]"
Node types that prevent the menu from showing.
hideWhenActiveMarks
string[]
default:"[]"
Mark types that prevent the menu from showing.
placement
'top' | 'bottom'
default:"'bottom'"
Position relative to the selection.
offset
number
default:"8"
Distance from the selection in pixels.
onHide
() => void
Called when the bubble menu is hidden.

bubbleMenuTriggers

Factory for common trigger functions:

Text formatting items

Button components

Image components


Custom menu example

Here’s a complete custom link bubble menu built from compound components:
The LinkToolbar automatically hides when LinkEditLink is clicked, and LinkForm appears in its place. When the user submits or cancels, the toolbar reappears.

Context

Use useBubbleMenuContext() inside any child of BubbleMenu to access the editor and editing state:

CSS import

@react-email/editor/themes/default.css bundles all UI component styles. Unless you need to cherry-pick, use this single import: