Files

154 lines
4.5 KiB
Plaintext

---
title: "Bubble Menu"
sidebarTitle: "Bubble Menu"
description: "Add floating formatting toolbars that appear on text selection."
icon: "message-lines"
---
## Quick start
Add `BubbleMenu` as a child of `EditorProvider` to get a fully-featured formatting toolbar.
```tsx
import { StarterKit } from '@react-email/editor/extensions';
import { BubbleMenu } from '@react-email/editor/ui';
import { EditorProvider } from '@tiptap/react';
import '@react-email/editor/themes/default.css';
const extensions = [StarterKit];
export function MyEditor() {
return (
<EditorProvider extensions={extensions} content={content}>
<BubbleMenu />
</EditorProvider>
);
}
```
Select text to see the toolbar with formatting, alignment, node type selection, and link controls.
When `BubbleMenu` has no children, it renders the default text formatting toolbar automatically.
<Tip>
Even though you can [compose BubbleMenu from
primitives](#composing-from-primitives) and style it that way, the default
can also be styled using <br/> [CSS variables and `data-re-*` selectors](/editor/features/styling#bubble-menu).
</Tip>
## Hiding on specific nodes or marks
Prevent the bubble menu from appearing on certain node types or when certain marks are active.
```tsx
<BubbleMenu
hideWhenActiveNodes={['codeBlock', 'button']}
hideWhenActiveMarks={['link']}
/>
```
This is useful when combining the text bubble menu with contextual menus for links, images, or buttons -- each gets its own menu via `BubbleMenu`.
```tsx
import { BubbleMenu, bubbleMenuTriggers } from '@react-email/editor/ui';
import { PluginKey } from '@tiptap/pm/state';
const linkPluginKey = new PluginKey('linkBubbleMenu');
<>
{/* Hide text bubble menu on links and buttons -- their own menus handle those */}
<BubbleMenu hideWhenActiveNodes={['button']} hideWhenActiveMarks={['link']} />
<BubbleMenu
trigger={bubbleMenuTriggers.nodeWithoutSelection('link')}
pluginKey={linkPluginKey}
>
<BubbleMenu.LinkToolbar>
<BubbleMenu.LinkEditLink />
<BubbleMenu.LinkOpenLink />
<BubbleMenu.LinkUnlink />
</BubbleMenu.LinkToolbar>
</BubbleMenu>
</>
```
## Composing from primitives
For full control, build a custom bubble menu using the compound component API.
```tsx
import { StarterKit } from '@react-email/editor/extensions';
import { BubbleMenu } from '@react-email/editor/ui';
import { EditorProvider } from '@tiptap/react';
export function MyEditor() {
return (
<EditorProvider extensions={[StarterKit]} content={content}>
<BubbleMenu>
<BubbleMenu.ItemGroup>
<BubbleMenu.Bold />
<BubbleMenu.Italic />
<BubbleMenu.Underline />
</BubbleMenu.ItemGroup>
<BubbleMenu.ItemGroup>
<BubbleMenu.AlignLeft />
<BubbleMenu.AlignCenter />
<BubbleMenu.AlignRight />
</BubbleMenu.ItemGroup>
</BubbleMenu>
</EditorProvider>
);
}
```
`BubbleMenu` wraps everything, `BubbleMenu.ItemGroup` creates visual groupings,
and individual items render the toggle buttons.
## Available items
| Component | Description |
| -- | -- |
| `BubbleMenu.Bold` | Bold toggle |
| `BubbleMenu.Italic` | Italic toggle |
| `BubbleMenu.Underline` | Underline toggle |
| `BubbleMenu.Strike` | Strikethrough toggle |
| `BubbleMenu.Code` | Inline code toggle |
| `BubbleMenu.Uppercase` | Uppercase toggle |
| `BubbleMenu.AlignLeft` | Left alignment |
| `BubbleMenu.AlignCenter` | Center alignment |
| `BubbleMenu.AlignRight` | Right alignment |
| `BubbleMenu.NodeSelector` | Block type dropdown (paragraph, h1-h3, etc.) |
| `BubbleMenu.LinkSelector` | Link add/edit popover |
| `BubbleMenu.Separator` | Visual separator between groups |
## Placement and offset
Control where the bubble menu appears relative to the selection.
```tsx
<BubbleMenu placement="top" offset={12}>
{/* items */}
</BubbleMenu>
```
<ResponseField name="placement" type="'top' | 'bottom'" default="'bottom'">
Whether the menu appears above or below the selection.
</ResponseField>
<ResponseField name="offset" type="number" default="8">
Distance from the selection in pixels.
</ResponseField>
## Examples
See bubble menus in action with runnable examples:
<CardGroup cols={2}>
<Card title="Bubble Menu" icon="code" href="https://react.email/editor/examples/bubble-menu">
Default bubble menu with text selection.
</Card>
<Card title="Custom Bubble Menu" icon="code" href="https://react.email/editor/examples/custom-bubble-menu">
Composing a custom menu from primitives.
</Card>
</CardGroup>