umbraco-tiptap-toolbar-extension

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Umbraco Tiptap Toolbar Extension

Umbraco Tiptap 工具栏扩展

What is it?

什么是Tiptap工具栏扩展?

A Tiptap Toolbar Extension adds buttons or controls to the Rich Text Editor's toolbar. It provides an
execute
method that runs when clicked, and can indicate active/disabled states. Several "kinds" are available:
button
(simple toggle),
colorPickerButton
(color selection),
menu
(dropdown menu), and
styleMenu
(style selection dropdown).
Tiptap工具栏扩展可为富文本编辑器的工具栏添加按钮或控件。它提供了一个
execute
方法,点击时会运行,并且可以指示激活/禁用状态。有多种类型可供选择:
button
(简单切换按钮)、
colorPickerButton
(颜色选择器按钮)、
menu
(下拉菜单)和
styleMenu
(样式选择下拉菜单)。

Documentation

文档参考

Related Skills

相关技能

  • Tiptap Extension: For adding editor functionality
    • Reference skill:
      umbraco-tiptap-extension
  • Modals: When toolbar buttons open modal dialogs
    • Reference skill:
      umbraco-modals
  • Tiptap 扩展:用于添加编辑器功能
    • 参考技能:
      umbraco-tiptap-extension
  • 模态框:当工具栏按钮需要打开模态对话框时使用
    • 参考技能:
      umbraco-modals

Workflow

实现流程

  1. Fetch docs - Use WebFetch on the URLs above
  2. Ask questions - Button, menu, or color picker? What action to execute?
  3. Generate files - Create manifest + API class based on latest docs
  4. Explain - Show what was created and how to test
  1. 获取文档 - 通过WebFetch获取上述链接的最新文档
  2. 确认需求 - 确定是按钮、菜单还是颜色选择器?需要执行什么操作?
  3. 生成文件 - 根据最新文档创建清单文件(manifest)和API类
  4. 说明解释 - 展示创建的内容以及测试方法

Minimal Examples

最简示例

Button Kind Manifest (manifests.ts)

按钮类型清单文件(manifests.ts)

typescript
import type { ManifestTiptapToolbarExtensionButtonKind } from '@umbraco-cms/backoffice/extension-registry';

const manifest: ManifestTiptapToolbarExtensionButtonKind = {
  type: 'tiptapToolbarExtension',
  kind: 'button',
  alias: 'My.TiptapToolbar.Bold',
  name: 'Bold Toolbar Button',
  api: () => import('./bold.tiptap-toolbar-api.js'),
  forExtensions: ['Umb.Tiptap.Bold'], // Links to the tiptap extension
  meta: {
    alias: 'bold',
    icon: 'icon-bold',
    label: 'Bold',
  },
};

export const manifests = [manifest];
typescript
import type { ManifestTiptapToolbarExtensionButtonKind } from '@umbraco-cms/backoffice/extension-registry';

const manifest: ManifestTiptapToolbarExtensionButtonKind = {
  type: 'tiptapToolbarExtension',
  kind: 'button',
  alias: 'My.TiptapToolbar.Bold',
  name: 'Bold Toolbar Button',
  api: () => import('./bold.tiptap-toolbar-api.js'),
  forExtensions: ['Umb.Tiptap.Bold'], // Links to the tiptap extension
  meta: {
    alias: 'bold',
    icon: 'icon-bold',
    label: 'Bold',
  },
};

export const manifests = [manifest];

Button API (bold.tiptap-toolbar-api.ts)

按钮API文件(bold.tiptap-toolbar-api.ts)

typescript
import { UmbTiptapToolbarElementApiBase } from '@umbraco-cms/backoffice/tiptap';
import type { Editor } from '@tiptap/core';

export default class BoldToolbarApi extends UmbTiptapToolbarElementApiBase {
  execute(editor?: Editor) {
    editor?.chain().focus().toggleBold().run();
  }
}
typescript
import { UmbTiptapToolbarElementApiBase } from '@umbraco-cms/backoffice/tiptap';
import type { Editor } from '@tiptap/core';

export default class BoldToolbarApi extends UmbTiptapToolbarElementApiBase {
  execute(editor?: Editor) {
    editor?.chain().focus().toggleBold().run();
  }
}

Button with Custom Active/Disabled State

自定义激活/禁用状态的按钮

typescript
import { UmbTiptapToolbarElementApiBase } from '@umbraco-cms/backoffice/tiptap';
import type { Editor } from '@tiptap/core';

export default class CustomToolbarApi extends UmbTiptapToolbarElementApiBase {
  execute(editor?: Editor) {
    editor?.chain().focus().toggleHighlight().run();
  }

  // Override to customize active state detection
  isActive(editor?: Editor): boolean {
    return editor?.isActive('highlight') ?? false;
  }

  // Override to customize disabled state
  isDisabled(editor?: Editor): boolean {
    return !editor?.can().toggleHighlight() ?? true;
  }
}
typescript
import { UmbTiptapToolbarElementApiBase } from '@umbraco-cms/backoffice/tiptap';
import type { Editor } from '@tiptap/core';

export default class CustomToolbarApi extends UmbTiptapToolbarElementApiBase {
  execute(editor?: Editor) {
    editor?.chain().focus().toggleHighlight().run();
  }

  // 重写方法自定义激活状态检测
  isActive(editor?: Editor): boolean {
    return editor?.isActive('highlight') ?? false;
  }

  // 重写方法自定义禁用状态
  isDisabled(editor?: Editor): boolean {
    return !editor?.can().toggleHighlight() ?? true;
  }
}

Menu Kind Manifest

菜单类型清单文件

typescript
import type { ManifestTiptapToolbarExtensionMenuKind } from '@umbraco-cms/backoffice/extension-registry';

const manifest: ManifestTiptapToolbarExtensionMenuKind = {
  type: 'tiptapToolbarExtension',
  kind: 'menu',
  alias: 'My.TiptapToolbar.Headings',
  name: 'Headings Menu',
  api: () => import('./headings.tiptap-toolbar-api.js'),
  forExtensions: ['Umb.Tiptap.Heading'],
  meta: {
    alias: 'headings',
    icon: 'icon-heading',
    label: 'Headings',
    look: 'text', // 'icon' or 'text'
  },
  items: [
    { label: 'Heading 1', data: { level: 1 } },
    { label: 'Heading 2', data: { level: 2 } },
    { label: 'Heading 3', data: { level: 3 } },
    { label: 'Paragraph', data: { level: 0 } },
  ],
};
typescript
import type { ManifestTiptapToolbarExtensionMenuKind } from '@umbraco-cms/backoffice/extension-registry';

const manifest: ManifestTiptapToolbarExtensionMenuKind = {
  type: 'tiptapToolbarExtension',
  kind: 'menu',
  alias: 'My.TiptapToolbar.Headings',
  name: 'Headings Menu',
  api: () => import('./headings.tiptap-toolbar-api.js'),
  forExtensions: ['Umb.Tiptap.Heading'],
  meta: {
    alias: 'headings',
    icon: 'icon-heading',
    label: 'Headings',
    look: 'text', // 'icon' or 'text'
  },
  items: [
    { label: 'Heading 1', data: { level: 1 } },
    { label: 'Heading 2', data: { level: 2 } },
    { label: 'Heading 3', data: { level: 3 } },
    { label: 'Paragraph', data: { level: 0 } },
  ],
};

Menu API

菜单API文件

typescript
import { UmbTiptapToolbarElementApiBase } from '@umbraco-cms/backoffice/tiptap';
import type { Editor } from '@tiptap/core';

export default class HeadingsToolbarApi extends UmbTiptapToolbarElementApiBase {
  execute(editor?: Editor, level?: number) {
    if (level === 0) {
      editor?.chain().focus().setParagraph().run();
    } else {
      editor?.chain().focus().toggleHeading({ level: level as 1 | 2 | 3 | 4 | 5 | 6 }).run();
    }
  }

  isActive(editor?: Editor, level?: number): boolean {
    if (level === 0) {
      return editor?.isActive('paragraph') ?? false;
    }
    return editor?.isActive('heading', { level }) ?? false;
  }
}
typescript
import { UmbTiptapToolbarElementApiBase } from '@umbraco-cms/backoffice/tiptap';
import type { Editor } from '@tiptap/core';

export default class HeadingsToolbarApi extends UmbTiptapToolbarElementApiBase {
  execute(editor?: Editor, level?: number) {
    if (level === 0) {
      editor?.chain().focus().setParagraph().run();
    } else {
      editor?.chain().focus().toggleHeading({ level: level as 1 | 2 | 3 | 4 | 5 | 6 }).run();
    }
  }

  isActive(editor?: Editor, level?: number): boolean {
    if (level === 0) {
      return editor?.isActive('paragraph') ?? false;
    }
    return editor?.isActive('heading', { level }) ?? false;
  }
}

Style Menu Kind

样式菜单类型

typescript
import type { ManifestTiptapToolbarExtensionStyleMenuKind } from '@umbraco-cms/backoffice/extension-registry';

const manifest: ManifestTiptapToolbarExtensionStyleMenuKind = {
  type: 'tiptapToolbarExtension',
  kind: 'styleMenu',
  alias: 'My.TiptapToolbar.Styles',
  name: 'Style Menu',
  api: () => import('./styles.tiptap-toolbar-api.js'),
  meta: {
    alias: 'styles',
    icon: 'icon-palette',
    label: 'Styles',
  },
  items: [
    {
      label: 'Lead Paragraph',
      data: { class: 'lead' },
      appearance: { style: 'font-size: 1.2em' },
    },
    {
      label: 'Small Text',
      data: { class: 'small' },
      appearance: { style: 'font-size: 0.85em' },
    },
    {
      label: 'Highlight Box',
      data: { class: 'highlight-box' },
    },
  ],
};
typescript
import type { ManifestTiptapToolbarExtensionStyleMenuKind } from '@umbraco-cms/backoffice/extension-registry';

const manifest: ManifestTiptapToolbarExtensionStyleMenuKind = {
  type: 'tiptapToolbarExtension',
  kind: 'styleMenu',
  alias: 'My.TiptapToolbar.Styles',
  name: 'Style Menu',
  api: () => import('./styles.tiptap-toolbar-api.js'),
  meta: {
    alias: 'styles',
    icon: 'icon-palette',
    label: 'Styles',
  },
  items: [
    {
      label: 'Lead Paragraph',
      data: { class: 'lead' },
      appearance: { style: 'font-size: 1.2em' },
    },
    {
      label: 'Small Text',
      data: { class: 'small' },
      appearance: { style: 'font-size: 0.85em' },
    },
    {
      label: 'Highlight Box',
      data: { class: 'highlight-box' },
    },
  ],
};

Color Picker Button Kind

颜色选择器按钮类型

typescript
import type { ManifestTiptapToolbarExtensionColorPickerButtonKind } from '@umbraco-cms/backoffice/extension-registry';

const manifest: ManifestTiptapToolbarExtensionColorPickerButtonKind = {
  type: 'tiptapToolbarExtension',
  kind: 'colorPickerButton',
  alias: 'My.TiptapToolbar.TextColor',
  name: 'Text Color',
  api: () => import('./text-color.tiptap-toolbar-api.js'),
  meta: {
    alias: 'textColor',
    icon: 'icon-palette',
    label: 'Text Color',
  },
};
typescript
import type { ManifestTiptapToolbarExtensionColorPickerButtonKind } from '@umbraco-cms/backoffice/extension-registry';

const manifest: ManifestTiptapToolbarExtensionColorPickerButtonKind = {
  type: 'tiptapToolbarExtension',
  kind: 'colorPickerButton',
  alias: 'My.TiptapToolbar.TextColor',
  name: 'Text Color',
  api: () => import('./text-color.tiptap-toolbar-api.js'),
  meta: {
    alias: 'textColor',
    icon: 'icon-palette',
    label: 'Text Color',
  },
};

Toolbar Button Opening Modal

打开模态框的工具栏按钮

typescript
import { UmbTiptapToolbarElementApiBase } from '@umbraco-cms/backoffice/tiptap';
import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
import type { Editor } from '@tiptap/core';

export default class LinkToolbarApi extends UmbTiptapToolbarElementApiBase {
  async execute(editor?: Editor) {
    const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);

    const modal = modalManager.open(this, MY_LINK_MODAL, {
      data: {
        currentHref: editor?.getAttributes('link').href,
      },
    });

    const result = await modal.onSubmit();
    if (result?.href) {
      editor?.chain().focus().setLink({ href: result.href }).run();
    }
  }
}
typescript
import { UmbTiptapToolbarElementApiBase } from '@umbraco-cms/backoffice/tiptap';
import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
import type { Editor } from '@tiptap/core';

export default class LinkToolbarApi extends UmbTiptapToolbarElementApiBase {
  async execute(editor?: Editor) {
    const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);

    const modal = modalManager.open(this, MY_LINK_MODAL, {
      data: {
        currentHref: editor?.getAttributes('link').href,
      },
    });

    const result = await modal.onSubmit();
    if (result?.href) {
      editor?.chain().focus().setLink({ href: result.href }).run();
    }
  }
}

Toolbar Extension Kinds

工具栏扩展类型

KindUse Case
button
Simple toggle button
colorPickerButton
Color selection
menu
Dropdown with options
styleMenu
Style/class selection
类型使用场景
button
简单切换按钮
colorPickerButton
颜色选择
menu
带选项的下拉菜单
styleMenu
样式/类选择

Meta Properties

元属性

PropertyDescription
alias
Used for isActive detection
icon
Toolbar button icon
label
Tooltip text
look
(menu only) 'icon' or 'text'
That's it! Always fetch fresh docs, keep examples minimal, generate complete working code.
属性说明
alias
用于激活状态检测
icon
工具栏按钮图标
label
提示文本(Tooltip)
look
(仅菜单类型)可选'icon'或'text'
就是这样!请始终获取最新文档,示例保持最简,生成可直接运行的完整代码。