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 CodeMirror extension

npm i @veltdev/codemirror-velt-comments

Step 3: Configure the CodeMirror editor with the Velt Comments extension

import { EditorView, basicSetup } from 'codemirror';
import { CodemirrorVeltComments } from '@veltdev/codemirror-velt-comments';

const view = new EditorView({
  doc: 'Your initial content here',
  extensions: [
    basicSetup,
    CodemirrorVeltComments(),
    // ... other extensions
  ],
  parent: editorRef.current,
});

Step 4: Add a comment button to your CodeMirror editor

Add a button that users can click to add comments after selecting text. Important: When clicking a button, the browser moves focus to the button which clears the editor selection. You need to save the selection on mousedown (before focus changes) and restore it before adding the comment.
import { useRef, useState, useEffect } from 'react';
import { EditorView, basicSetup } from 'codemirror';
import { CodemirrorVeltComments, addComment, renderComments } from '@veltdev/codemirror-velt-comments';
import { useCommentAnnotations } from '@veltdev/react';

function CodeMirrorEditor() {
  const editorRef = useRef(null);
  const [editorView, setEditorView] = useState(null);
  const savedSelectionRef = useRef(null);
  const annotations = useCommentAnnotations();

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

    const view = new EditorView({
      doc: 'Your initial content here',
      extensions: [
        basicSetup,
        CodemirrorVeltComments(),
      ],
      parent: editorRef.current,
    });

    setEditorView(view);
    return () => view.destroy();
  }, []);

  useEffect(() => {
    if (editorView && annotations?.length) {
      renderComments({
        editor: editorView,
        commentAnnotations: annotations,
      });
    }
  }, [editorView, annotations]);

  const saveSelection = () => {
    if (editorView) {
      const { from, to } = editorView.state.selection.main;
      if (from !== to) {
        savedSelectionRef.current = { from, to };
      }
    }
  };

  const handleAddComment = () => {
    if (editorView) {
      if (savedSelectionRef.current) {
        const { from, to } = savedSelectionRef.current;
        if (from !== to) {
          editorView.dispatch({
            selection: { anchor: from, head: to }
          });
        }
      }
      addComment({ editor: editorView });
      savedSelectionRef.current = null;
    }
  };

  return (
    <div>
      <button
        onMouseDown={(e) => {
          e.preventDefault();
          saveSelection();
        }}
        onClick={handleAddComment}
      >
        Add Comment
      </button>
      <div ref={editorRef} />
    </div>
  );
}

Step 5: Call addComment to add a comment

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

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

addComment(addCommentRequest);

Step 6: Render comments in CodeMirror editor

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

const annotations = useCommentAnnotations();

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

Step 7: Persist Velt Comment Marks (optional)

  • By default, Velt comment marks (<velt-comment-text>) are persisted in the CodeMirror editor by Velt SDK. When the editor loads and the Velt SDK initializes, the marks will be automatically added to the editor.
  • If you plan to store the contents of the CodeMirror editor on your end with the comment marks already included, you can disable this feature.
  • Default: true
const editorView = new EditorView({
  extensions: [
    CodemirrorVeltComments({
      persistVeltMarks: false,
    }),
    // ... other extensions
  ],
  parent: editorRef.current,
});

Step 8: Style the commented text

  • You can style the commented text by adding CSS for the velt-comment-text element.
velt-comment-text {
  background-color: rgba(255, 255, 0, 0.3);
  border-bottom: 2px solid #ffcc00;
  cursor: pointer;
}

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

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

APIs

CodemirrorVeltComments()

Creates the Velt Comments extension for CodeMirror.
  • Params: config?: CodemirrorVeltCommentsConfig
    • editorId?: string - Unique identifier for this editor instance (for multi-editor scenarios)
    • persistVeltMarks?: boolean - Whether to persist Velt marks. Default: true
  • Returns: CodeMirror Extension
import { EditorView } from 'codemirror';
import { CodemirrorVeltComments } from '@veltdev/codemirror-velt-comments';

const view = new EditorView({
  extensions: [
    CodemirrorVeltComments({
      editorId: 'my-editor',
      persistVeltMarks: true,
    }),
  ],
  parent: editorRef.current,
});

addComment()

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

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

renderComments()

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

const annotations = useCommentAnnotations();

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