> ## 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.

# Bubble Menu

> Add floating formatting toolbars that appear on text selection.

## Quick start

Add `BubbleMenu` as a child of `EditorProvider` to get a fully-featured formatting toolbar.

```tsx theme={"theme":{"light":"github-light","dark":"vesper"}}
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 theme={"theme":{"light":"github-light","dark":"vesper"}}
<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 theme={"theme":{"light":"github-light","dark":"vesper"}}
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 theme={"theme":{"light":"github-light","dark":"vesper"}}
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 theme={"theme":{"light":"github-light","dark":"vesper"}}
<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>
