> ## Documentation Index
> Fetch the complete documentation index at: https://vuemail.dev/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.

```vue theme={null}
<script setup lang="ts">
import { EditorProvider } from '@vuemaildev/editor';
import { StarterKit } from '@vuemaildev/editor/extensions';
import { BubbleMenu } from '@vuemaildev/editor/ui';
import '@vuemaildev/editor/themes/default.css';

const extensions = [StarterKit];
</script>

<template>
  <EditorProvider :extensions="extensions" :content="content">
    <BubbleMenu />
  </EditorProvider>
</template>
```

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 \
> &#x20;[CSS variables and `data-re-*` selectors](https://vuemail.dev/docs/editor/features/styling#bubble-menu).

## Hiding on specific nodes or marks

Prevent the bubble menu from appearing on certain node types or when certain marks are active.

```vue theme={null}
<BubbleMenu
  :hide-when-active-nodes="['codeBlock', 'button']"
  :hide-when-active-marks="['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`.

```vue theme={null}
<script setup lang="ts">
import { BubbleMenu, bubbleMenuTriggers } from '@vuemaildev/editor/ui';
import { PluginKey } from '@tiptap/pm/state';

const linkPluginKey = new PluginKey('linkBubbleMenu');
const linkTrigger = bubbleMenuTriggers.nodeWithoutSelection('link');
</script>

<template>
  <!-- Hide text bubble menu on links and buttons -- their own menus handle those -->
  <BubbleMenu :hide-when-active-nodes="['button']" :hide-when-active-marks="['link']" />

  <BubbleMenu :trigger="linkTrigger" :plugin-key="linkPluginKey">
    <BubbleMenu.LinkToolbar>
      <BubbleMenu.LinkEditLink />
      <BubbleMenu.LinkOpenLink />
      <BubbleMenu.LinkUnlink />
    </BubbleMenu.LinkToolbar>
  </BubbleMenu>
</template>
```

## Composing from primitives

For full control, build a custom bubble menu using the compound component API.

```vue theme={null}
<script setup lang="ts">
import { EditorProvider } from '@vuemaildev/editor';
import { StarterKit } from '@vuemaildev/editor/extensions';
import { BubbleMenu } from '@vuemaildev/editor/ui';

const extensions = [StarterKit];
</script>

<template>
  <EditorProvider :extensions="extensions" :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>
</template>
```

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

```vue theme={null}
<BubbleMenu placement="top" :offset="12">
  <!-- items -->
</BubbleMenu>
```

**placement** `'top' | 'bottom'` (default: 'bottom')

Whether the menu appears above or below the selection.

**offset** `number` (default: 8)

Distance from the selection in pixels.

## Examples

See bubble menus in action with runnable examples:

> **[Bubble Menu](https://vuemail.dev/editor/bubble-menu)**
>
> Default bubble menu with text selection.

> **[Custom Bubble Menu](https://vuemail.dev/editor/custom-bubble-menu)**
>
> Composing a custom menu from primitives.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.