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.
<VeltProvider apiKey="API_KEY">
  <VeltComments textMode={false} />
</VeltProvider>

Step 2: Install the Velt ProseMirror extension

npm i @veltdev/prosemirror-velt-comments prosemirror-model prosemirror-state prosemirror-view
For the examples below, also install the standard ProseMirror example packages:
npm i prosemirror-schema-basic prosemirror-example-setup

Step 3: Configure the ProseMirror editor with the Velt Comments plugin

Add VeltCommentsPlugin to the plugins array when creating your EditorState.
import { useEffect, useRef } from 'react';
import { schema } from 'prosemirror-schema-basic';
import { exampleSetup } from 'prosemirror-example-setup';
import { EditorState } from 'prosemirror-state';
import { EditorView } from 'prosemirror-view';
import { VeltCommentsPlugin } from '@veltdev/prosemirror-velt-comments';

const EDITOR_ID = 'my-editor';

function ProseMirrorEditor() {
  const containerRef = useRef(null);
  const viewRef = useRef(null);

  useEffect(() => {
    if (!containerRef.current) return;

    const state = EditorState.create({
      schema,
      plugins: [
        ...exampleSetup({ schema }),
        VeltCommentsPlugin({ editorId: EDITOR_ID }),
      ],
    });

    const view = new EditorView(containerRef.current, { state });
    viewRef.current = view;

    return () => {
      view.destroy();
      viewRef.current = null;
    };
  }, []);

  return <div ref={containerRef} />;
}

Step 4: Add a comment button to your ProseMirror editor

Add a button that users can click to add comments after selecting text in the ProseMirror editor. Important: Use onMouseDown with preventDefault() so the browser does not move focus away from the editor before addComment reads the current selection.
import { addComment } from '@veltdev/prosemirror-velt-comments';

const handleAddComment = () => {
  if (!viewRef.current) return;

  addComment({
    editor: viewRef.current,
    editorId: EDITOR_ID,
  });
};

<button
  onMouseDown={(event) => event.preventDefault()}
  onClick={handleAddComment}
>
  Add Comment
</button>

Step 5: Call addComment to add a comment

  • Call this method to add a comment to selected text in the ProseMirror editor.
  • Params: AddCommentRequest. It has the following properties:
    • editor: ProseMirror EditorView.
    • editorId: Id of the editor. Use this if you have multiple ProseMirror editors on the same page. (optional)
    • context: Add custom metadata to the Comment Annotation. Learn more. (optional)
import { addComment } from '@veltdev/prosemirror-velt-comments';

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

addComment(addCommentRequest);

Step 6: Render comments in ProseMirror editor

  • Get the comment data from Velt SDK and render it in the ProseMirror editor.
  • Params: RenderCommentsRequest. It has the following properties:
    • editor: ProseMirror EditorView.
    • editorId: Id of the editor. Use this if you have multiple ProseMirror editors on the same page. (optional)
    • commentAnnotations: Array of Comment Annotation objects.
import { useEffect } from 'react';
import { useCommentAnnotations } from '@veltdev/react';
import { renderComments } from '@veltdev/prosemirror-velt-comments';

const commentAnnotations = useCommentAnnotations();

useEffect(() => {
  if (!viewRef.current) return;

  renderComments({
    editor: viewRef.current,
    editorId: 'EDITOR_ID',
    commentAnnotations: commentAnnotations ?? [],
  });
}, [commentAnnotations]);

Step 7: Re-apply ProseMirror comment highlights (optional)

  • ProseMirror renders comment highlights as view-only overlay elements.
  • The integration does not write Velt comment marks into your ProseMirror schema or saved document.
  • Save your ProseMirror document normally. After you recreate the EditorView or replace document content, call renderComments again.
const json = view.state.doc.toJSON();
// Save json to your backend.

renderComments({
  editor: view,
  editorId: 'EDITOR_ID',
  commentAnnotations,
});

Step 8: Style the commented text

  • You can style the commented text by adding CSS for the velt-comment-text element.
  • Use the comment-available attribute to apply styles only after comment data has loaded.
velt-comment-text[comment-available="true"] {
  background-color: rgba(255, 255, 0, 0.3);
  border-bottom: 2px solid #ffcc00;
  cursor: pointer;
}

velt-comment-text[comment-available="true"]:hover {
  background-color: rgba(255, 255, 0, 0.5);
}

velt-comment-text.velt-comment-selected {
  background-color: rgba(255, 255, 0, 0.5);
}

Complete Example

APIs

VeltCommentsPlugin()

Creates the ProseMirror plugin that powers Velt comments. Add it to your editor state’s plugins array.
import { schema } from 'prosemirror-schema-basic';
import { exampleSetup } from 'prosemirror-example-setup';
import { EditorState } from 'prosemirror-state';
import { VeltCommentsPlugin } from '@veltdev/prosemirror-velt-comments';

const state = EditorState.create({
  schema,
  plugins: [
    ...exampleSetup({ schema }),
    VeltCommentsPlugin({ editorId: 'my-editor' }),
  ],
});

addComment()

Creates a comment annotation for the currently selected text in the editor.
import { addComment } from '@veltdev/prosemirror-velt-comments';

const handleAddComment = () => {
  if (!viewRef.current) return;
  addComment({ editor: viewRef.current, editorId: 'my-editor' });
};

<button
  onMouseDown={(event) => event.preventDefault()}
  onClick={handleAddComment}
>
  Comment
</button>

renderComments()

Renders and highlights comment annotations in the ProseMirror editor.
import { useEffect } from 'react';
import { useCommentAnnotations } from '@veltdev/react';
import { renderComments } from '@veltdev/prosemirror-velt-comments';

const annotations = useCommentAnnotations();

useEffect(() => {
  if (!viewRef.current) return;

  renderComments({
    editor: viewRef.current,
    editorId: 'my-editor',
    commentAnnotations: annotations ?? [],
  });
}, [annotations]);

veltCommentsPluginKey

The ProseMirror PluginKey used by the package. Use it only for advanced inspection of plugin state.
  • Params: none
  • Returns: PluginKey
import { veltCommentsPluginKey } from '@veltdev/prosemirror-velt-comments';

const state = veltCommentsPluginKey.getState(view.state);
const anchors = state?.anchors;