EditorToolbar

GitLab
Uma barra de ferramentas personalizável para ações do editor que pode ser exibida como menu fixo, bubble ou flutuante.

Uso

O componente EditorToolbar exibe uma barra de ferramentas com botões de formatação que sincronizam automaticamente seu estado ativo com o conteúdo do editor. Ele suporta três modos de layout usando o pacote @tiptap/vue-3/menus:

  • fixed (always visible)
  • bubble (appears on text selection)
  • floating (appears on empty lines)
Ele deve ser usado dentro do slot padrão de um componente Editor para ter acesso à instância do editor.
Os layouts bubble e floating usam as extensões BubbleMenu e FloatingMenu do TipTap.

Itens

Use a prop items como um array de objetos com as seguintes propriedades:

Você pode passar qualquer propriedade do componente Button, como color, variant, size, etc.

Você também pode passar um array de arrays para a prop items para criar grupos separados de itens.
Cada item pode receber um array items de objetos com as mesmas propriedades da prop items para criar um DropdownMenu.

Layout

Use a prop layout para alterar como a barra de ferramentas é exibida. O padrão é fixed.

Opções

Ao usar os layouts bubble ou floating, use a prop options para personalizar o comportamento de posicionamento usando as opções do Floating UI.

<template>
  <NEditor v-slot="{ editor }">
    <NEditorToolbar
      :editor="editor"
      :items="items"
      layout="bubble"
      :options="{
        placement: 'top',
        offset: 8,
        flip: { padding: 8 },
        shift: { padding: 8 }
      }"
    />
  </NEditor>
</template>

Deve exibir

Ao usar os layouts bubble ou floating, use a prop should-show para controlar quando a barra de ferramentas aparece. Essa função recebe o contexto sobre o estado do editor e retorna um booleano.

<template>
  <NEditor v-slot="{ editor }">
    <NEditorToolbar
      :editor="editor"
      :items="items"
      layout="bubble"
      :should-show="({ view, state }) => {
        const { selection } = state
        const { from, to } = selection
        const text = state.doc.textBetween(from, to)
        return view.hasFocus() && !selection.empty && text.length > 10
      }"
    />
  </NEditor>
</template>

Exemplos

Com barra de ferramentas de imagem

Use a prop should-show para criar barras de ferramentas específicas de contexto que aparecem apenas para certos tipos de node. Este exemplo mostra uma barra de ferramentas bubble com ações de download e exclusão que só aparece quando uma imagem é selecionada.

Este exemplo demonstra como criar um popover de link personalizado usando a propriedade slot nos itens da barra de ferramentas e o componente Popover.

  1. Crie um componente Vue que envolve um Popover com funcionalidade de edição de link:
undefined.vue
  1. Use o componente personalizado na barra de ferramentas com um slot nomeado:

API

Props

Prop Default Type
as'div'any

The element or component this component should render as.

editorEditor
color'neutral' "primary" | "secondary" | "accent" | "success" | "info" | "warning" | "error" | "neutral"

The color of the toolbar controls.

variant'ghost' "solid" | "outline" | "soft" | "subtle" | "ghost" | "link"

The variant of the toolbar controls.

activeColor'primary' "primary" | "secondary" | "accent" | "success" | "info" | "warning" | "error" | "neutral"

The color of the active toolbar control.

activeVariant'soft' "solid" | "outline" | "soft" | "subtle" | "ghost" | "link"

The variant of the active toolbar control.

size'sm' "xs" | "sm" | "md" | "lg" | "xl"

The size of the toolbar controls.

items T
layout'fixed' "fixed" | "floating" | "bubble"
pluginKeyunknown

The plugin key. The plugin key for the floating menu.

updateDelayunknown

The delay in milliseconds before the menu should be updated. This can be useful to prevent performance issues.

resizeDelayunknown

The delay in milliseconds before the menu position should be updated on window resize. This can be useful to prevent performance issues.

shouldShowunknown

A function that determines whether the menu should be shown or not. If this function returns false, the menu will be hidden, otherwise it will be shown.

appendTounknown

The DOM element to append your menu to. Default is the editor's parent element.

Sometimes the menu needs to be appended to a different DOM context due to accessibility, clipping, or z-index issues.

getReferencedVirtualElementunknown

A function that returns the virtual element for the menu. This is useful when the menu needs to be positioned relative to a specific DOM element.

optionsunknown

The options for the bubble menu. Those are passed to Floating UI and include options for the placement, offset, flip, shift, arrow, size, autoPlacement, hide, and inline middlewares. The options for the floating menu. Those are passed to Floating UI and include options for the placement, offset, flip, shift, arrow, size, autoPlacement, hide, and inline middlewares.

ui { root?: SlotClass; base?: SlotClass; group?: SlotClass; separator?: SlotClass; }

Slots

Slot Type
item{ item: NestedItem<T>; } & SlotPropsProps

Tema

app.config.ts
export default defineAppConfig({
  ui: {
    editorToolbar: {
      slots: {
        root: 'focus:outline-none',
        base: 'flex items-stretch gap-1.5',
        group: 'flex items-center gap-0.5',
        separator: 'w-px self-stretch bg-border'
      },
      variants: {
        layout: {
          bubble: {
            base: 'bg-default border border-default rounded-lg p-1'
          },
          floating: {
            base: 'bg-default border border-default rounded-lg p-1'
          },
          fixed: {
            base: ''
          }
        }
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nitro/ui/vite'

export default defineConfig({
  plugins: [
    vue(),
    ui({
      ui: {
        editorToolbar: {
          slots: {
            root: 'focus:outline-none',
            base: 'flex items-stretch gap-1.5',
            group: 'flex items-center gap-0.5',
            separator: 'w-px self-stretch bg-border'
          },
          variants: {
            layout: {
              bubble: {
                base: 'bg-default border border-default rounded-lg p-1'
              },
              floating: {
                base: 'bg-default border border-default rounded-lg p-1'
              },
              fixed: {
                base: ''
              }
            }
          }
        }
      }
    })
  ]
})

Changelog

No recent changes