Skip to main content

Setup

Step 1: Add Comment components

  • Add the Velt Comments component to the root of your app.
  • This component is required to render comments in your app.
  • Set the text mode prop to false to hide the default text comment tool.
  • React / Next.js
  • Other Frameworks
<VeltProvider apiKey="API_KEY">
  <VeltComments textMode={false} />
</VeltProvider>

Step 2: Install the Velt Tiptap extension

npm i @veltdev/tiptap-velt-comments

Step 3: Import and add the extension to your Tiptap editor

  • React / Next.js
  • Other Frameworks
import { TiptapVeltComments } from '@veltdev/tiptap-velt-comments';

const editor = new Editor({
  extensions: [
    TiptapVeltComments,
    // ... other extensions
  ],
});

Step 4: Add a comment button to Tiptap Bubble menu

Add a button in your existing bubble menu or create a new bubble menu that appears when users select text in the editor.
  • React / Next.js
  • Other Frameworks
import { BubbleMenu, EditorContent, useEditor } from '@tiptap/react';
import { addComment } from '@veltdev/tiptap-velt-comments';

export default function TipTapComponent() {
  const editor = useEditor({
    // ... your editor configuration
  });

  const addTiptapVeltComment = () => {
    if (editor) {
      addComment({ editor });
    }
  };

  return (
    <div>
      <EditorContent editor={editor} />

      {/* Bubble Menu for Comments */}
      {editor && (
        <BubbleMenu editor={editor} tippyOptions={{ duration: 100 }}>
          <div className="bubble-menu">
            <button
              className="comment-button"
              onClick={(e) => {
                e.preventDefault();
                e.stopPropagation();
                addTiptapVeltComment();
              }}
              title="Add comment"
            >
              <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" stroke="currentColor">
                <path
                  d="M10 17.25H4C3.30964 17.25 2.75 16.6904 2.75 16V10C2.75 5.99594 5.99594 2.75 10 2.75C14.0041 2.75 17.25 5.99594 17.25 10C17.25 14.0041 14.0041 17.25 10 17.25Z"
                  strokeWidth="1.5"
                />
              </svg>
            </button>
          </div>
        </BubbleMenu>
      )}
    </div>
  );
}
Refer to the Tiptap BubbleMenu documentation to learn more about customizing the bubble menu behavior.

Step 5: Call addComment to add a comment

  • Call this method to add a comment to selected text in the Tiptap editor. You can use this when the user clicks on the comment button in context menu or presses a keyboard shortcut.
  • Params: AddCommentRequest. It has the following properties:
    • editor: instance of the Tiptap editor.
    • editorId: Id of the tiptap editor. Use this if you have multiple tiptap editors on the same page in your app. (optional)
    • context: Add any custom metadata to the Comment Annotation. Learn more. (optional)
  • React / Next.js
  • Other Frameworks
import { addComment } from '@veltdev/tiptap-velt-comments';

const addCommentRequest = {
  editor,
  editorId: 'EDITOR_ID',
  context: {
    storyId: 'story-id',
    storyName: 'story-name',
  },
};

addComment(addCommentRequest);

Step 6: Render Comments in Tiptap Editor

  • Get the comment data from Velt SDK and render it in the Tiptap Editor.
  • Params: RenderCommentsRequest. It has the following properties:
    • editor: Instance of the Tiptap editor.
    • editorId: Id of the tiptap editor. Use this if you have multiple tiptap editors on the same page in your app. (optional)
    • commentAnnotations: Array of Comment Annotation objects.
  • React / Next.js
  • Other Frameworks
import { renderComments } from '@veltdev/tiptap-velt-comments';

const annotations = useCommentAnnotations();

useEffect(() => {
  if (editor && annotations?.length) {
    const renderCommentsRequest = {
      editor,
      editorId: 'EDITOR_ID',
      annotations,
    };
    renderComments(renderCommentsRequest);
  }
}, [editor, annotations]);

Step 7: Persist Velt Comment Marks (html tags)

  • By default, Velt comment marks (<velt-comment-text>) are persisted in the Tiptap editor by Velt SDK. When the editor loads and the velt sdk initializes, the marks will be automatically added to the editor by us.
  • If you plan to store the contents of the tiptap editor as raw html on your end then you should turn off this feature since you will already be storing the Velt comment marks.
  • Default: true
const editor = new Editor({
  extensions: [
    TiptapVeltComments.configure({
      persistVeltMarks: false
    }),
    // ... other extensions
  ],
});

Step 8: Style the commented text

  • You can style the commented text by adding a CSS class to the velt-comment-text element.
  • By using the comment-available attribute, you can apply styles only when the comment data has loaded.
velt-comment-text[comment-available="true"] {
  background-color: #ffff00;
}

Complete Example

APIs

TiptapVeltComments.configure()

A custom Tiptap extension for Velt comments.
  • React / Next.js
import { Editor } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
import { TiptapVeltComments } from '@veltdev/tiptap-velt-comments';

const editor = new Editor({
  extensions: [
    StarterKit,
    TiptapVeltComments.configure({
      persistVeltMarks: true,
      HTMLAttributes: { class: 'velt-comment' },
      editorId: 'my-doc-1',
    }),
  ],
  content: '<p>Hello Velt!</p>',
});

addComment()

Creates a comment annotation for the currently selected text in the editor.
  • Params:
  • Returns: Promise<void>
  • React / Next.js
import { addComment } from '@veltdev/tiptap-velt-comments';

<button
  onMouseDown={(e) => {
    e.preventDefault();
    addComment({ editor }); // optionally: { editor, editorId: 'my-doc-1', context: {...} }
  }}
>
  Comment
</button>

renderComments()

Renders and highlights comment annotations in the editor.
  • React / Next.js
import { renderComments } from '@veltdev/tiptap-velt-comments';
import type { CommentAnnotation } from '@veltdev/types';

useEffect(() => {
  if (editor && commentAnnotations) {
    renderComments({ editor, commentAnnotations, editorId: 'my-doc-1' });
  }
}, [editor, commentAnnotations]);