hunghg255 / reactjs-tiptap-editor

A modern WYSIWYG rich text editor based on tiptap and shadcn ui for Reactjs
https://reactjs-tiptap-editor.vercel.app/
MIT License
41 stars 10 forks source link

Feature Request: The content of the bubble menu is customizable #11

Closed condorheroblog closed 3 weeks ago

condorheroblog commented 3 weeks ago

For example, when my rich text editor doesn't require the Code extension, the code should run smoothly. However, there are currently errors because the content of the bubble menu is hardcoded and must be initialized.

image
{!props?.hideBubble && (
    <>
      <ColumnsMenu editor={editor} />
      <TableBubbleMenu editor={editor} />
      <ContentMenu editor={editor} disabled={props?.disabled} />

      <BubbleMenuLink editor={editor} disabled={props?.disabled} />
      <BubbleMenuText editor={editor} disabled={props?.disabled} />
      <BubbleMenuImage editor={editor as any} disabled={props?.disabled} />
      <BubbleMenuVideo editor={editor as any} disabled={props?.disabled} />
    </>
  )}

I think we should add a parameter similar to 'toolbar', perhaps called 'bubble'.

export interface GeneralOptions<T> {
  /** Enabled divider */
  divider: boolean;
  /** Enabled spacer */
  spacer: boolean;
  /** Button view function */
  button: ButtonView<T>;
  /** Show on Toolbar */
  toolbar?: boolean;
  /** Show on Bubble Menu */
  bubble?: boolean;
}

I've been researching this, but it's not finished yet. I'm also not very certain about some of the effects. What's your opinion?😂

hunghg255 commented 3 weeks ago

@condorheroblog I think we can try a dynamic array text extension like this.

const bubbleList = ['bold', 'italic', 'underline', 'strike', 'code', 'link', 'divider', 'color', 'highlight']

export function getBubbleText(editor: Editor, t: any) {
  const bubbleMenu = bubbleList.filter((type) => {
    if (type === 'divider') {
      return true
    }

    const ext = editor.extensionManager.extensions.find((ext: any) => ext.name === type)
    return !!ext
  }).map((it) => {
    const ext: any = editor.extensionManager.extensions.find((ext: any) => ext.name === it)
    if (it === 'divider') {
      return {
        type: 'divider',
        component: undefined,
        componentProps: {},
      }
    }

    return ext.configure().options.button({ editor, t } as any)
  })

  return bubbleMenu
}
hunghg255 commented 3 weeks ago

I understand your error, if we are not import extension when initial editor, we can not use extension in bubble menu

condorheroblog commented 3 weeks ago

Yes, no import no UI🤔

hunghg255 commented 3 weeks ago

Yes, no import no UI🤔

yes, I think it oke.

if want to show code on the bubble, we need to import Code extension to BaseKit and hide it

hunghg255 commented 3 weeks ago

or we can pass config toolbar to extension to hide/show extension icon on toolbar

export const Code = TiptapCode.extend<CodeOptions>({
  addOptions() {
    return {
      ...this.parent?.(),
+      toolbar: false,
      button: ({ editor, t }) => ({
        component: ActionButton,
        componentProps: {
          action: () => editor.commands.toggleCode(),
          isActive: () => editor.isActive('code') || false,
          disabled: !editor.can().toggleCode(),
          icon: 'Code',
          shortcutKeys: ['mod', 'E'],
          tooltip: t('editor.code.tooltip'),
        },
      }),
    }
  },
})
  Code.configure({ toolbar: true }),
condorheroblog commented 3 weeks ago
  1. I believe that we need to support a 'bubble' parameter. This can address the scenario where I want to import an extension that appears in the toolbar but not in the bubble menu.

  2. It's not just BubbleMenuText that needs to be adapted for dynamically importing extensions; the following components all need to be adapted as well.

<ColumnsMenu editor={editor} />
<TableBubbleMenu editor={editor} />
<ContentMenu editor={editor} disabled={disabled} />
<BubbleMenuLink editor={editor} disabled={disabled} />
<BubbleMenuText editor={editor} disabled={disabled} />
<BubbleMenuImage editor={editor} disabled={disabled} />
<BubbleMenuVideo editor={editor} disabled={disabled} />
  1. After completing the adaptation of components in the second step, May be we should be able to export these for users to use, or allow users to customize the configuration of the bubble menu.
hunghg255 commented 3 weeks ago

@condorheroblog ah you mean, We can make bubble menu dynamic content, currently I am hardcoding the content of the bubble. ok. We will think of ways to make your thing happen

condorheroblog commented 3 weeks ago

I think you understand what I mean is.


The ability to flexibly configure this feature is really exciting. The toolbar is even more commonly used. The plugin could support a standard mode, and then expose an API that exports all toolbar components to the user. Users could then customize the order and integration of these components. For example, users could implement a simplified mode.

image image
hunghg255 commented 3 weeks ago

so I think we need to have a step before showing icon (this step to add extension to editor) after that we can show/hide extension on toolbar menu or bubble menu.

option 2: need to rewrite bubble component