Toolbar & menus

Customise the toolbar, bubble menu, slash menu, drag handle and menubar.

Toolbar

The toolbar is generated from your extensions: every extension with a button contributes one or more controls, in the order of the extensions array.

const extensions = [
  BaseKit,
  History,                             // undo, redo
  Heading.configure({ spacer: true }), // separator before
  Bold,
  Italic,
  Link.configure({ divider: true }),   // separator after
  Table.configure({ toolbar: false }), // no button, feature still available
]
Option (all extensions)Description
spacerRender a separator before the button.
dividerRender a separator after the button.
toolbarfalse hides the button but keeps the extension.
buttonReplace the button entirely (see Custom extensions).

The toolbar follows the WAI-ARIA toolbar pattern: ← / → move between controls, Home / End jump to the ends. On touch devices it becomes a horizontally scrollable strip with 40 px touch targets.

Replacing a button

import { ActionButton, Bold } from 'vue-echo-editor'

Bold.configure({
  button: ({ editor, t }) => ({
    component: ActionButton,
    componentProps: {
      icon: 'Bold',
      tooltip: t('editor.bold.tooltip'),
      shortcutKeys: ['mod', 'B'],
      action: () => editor.chain().focus().toggleBold().run(),
      isActive: () => editor.isActive('bold'),
      disabled: !editor.can().toggleBold(),
    },
  }),
})

Bubble menu

Selecting text shows a bubble menu. Its content is configured on BaseKit per node type:

BaseKit.configure({
  bubble: {
    list: {
      text: ['bold', 'italic', 'underline', 'divider', 'link', 'color', 'highlight'],
      video: ['video-size-small', 'video-size-medium', 'video-size-large', 'divider', 'remove'],
    },
  },
})

Entries are extension names (bold, link, color, AI, textAlign …), divider, text-bubble (the block-type switcher) or the built-in video actions. Extensions that aren't registered are skipped automatically.

Links, tables, images and column layouts get their own context menus when those extensions are registered. On touch devices the bubble menu opens below the selection so it doesn't collide with the native selection toolbar.

Slash menu

Register SlashCommand and type / at the start of an empty line.

import { SlashCommand } from 'vue-echo-editor'
import type { Group } from 'vue-echo-editor'

SlashCommand.configure({
  getCommandGroups: ({ presetGroups, editor, lang }) => [
    ...presetGroups,
    {
      name: 'snippets',
      title: 'Snippets',
      commands: [
        {
          name: 'greeting',
          label: 'Greeting',
          aliases: ['hello', 'hi'],
          iconName: 'Sparkles',
          action: ({ editor, range }) => editor.chain().focus().deleteRange(range).insertContent('Hello 👋').run(),
        },
      ],
    },
  ] satisfies Group[],
})

Plugins can also contribute slash commands without touching this configuration.

Drag handle

A drag handle appears to the left of the hovered block (desktop only). It moves blocks by drag and drop and opens a block menu: delete, clear formatting, copy, duplicate, alignment and indentation. The + button inserts a new line and opens the slash menu.

Disable it — together with bubble menus — with hide-bubble.

A classic File / Edit / View / Insert / Format menubar is available:

<EchoEditor :extensions="extensions" :hide-menubar="false" />

Menu entries only appear when the extension they need is registered.