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

npm install @veltdev/lexical-velt-comments @veltdev/client lexical

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

  • Register the CommentNode and configure your Lexical editor.
import { LexicalComposer } from '@lexical/react/LexicalComposer';
import { CommentNode } from '@veltdev/lexical-velt-comments';

const initialConfig = {
  namespace: 'MyEditor',
  nodes: [CommentNode],
  onError: (error) => console.error(error),
};

function App() {
  return (
    <LexicalComposer initialConfig={initialConfig}>
      {/* Editor plugins */}
    </LexicalComposer>
  );
}

Step 4: Add a comment button

  • Add a button that users can click to add comments after selecting text.
import { useCallback } from 'react';
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import { addComment } from '@veltdev/lexical-velt-comments';

function AddCommentPlugin() {
  const [editor] = useLexicalComposerContext();

  const handleAddComment = useCallback(() => {
    addComment({ editor });
  }, [editor]);

  return (
    <button 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 Lexical editor. You can use this when the user clicks on a comment button or presses a keyboard shortcut.
  • Params: AddCommentRequest. It has the following properties:
    • editor: Instance of the Lexical Editor.
    • editorId: Id of the editor. Use this if you have multiple Lexical editors on the same page. (optional)
    • context: Add any custom metadata to the Comment Annotation. Learn more. (optional)
import { addComment } from '@veltdev/lexical-velt-comments';

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

addComment(addCommentRequest);

Step 6: Render comments in Lexical editor

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

const annotations = useCommentAnnotations();

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

Step 7: Persist Editor Content Without Velt Marks (optional)

  • When saving editor content to your backend, you may want to exclude Velt comment marks to keep the content clean.
  • Use exportJSONWithoutComments to export the editor state as JSON without Velt comment nodes.
import { exportJSONWithoutComments } from '@veltdev/lexical-velt-comments';

// Get clean editor state JSON without Velt comment marks
const cleanState = exportJSONWithoutComments(editor);

// Save to your backend
localStorage.setItem('editor-content', JSON.stringify(cleanState));

Step 8: Style the commented text

  • 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);
}

Complete Example

APIs

CommentNode

A custom Lexical node used to wrap commented text with comment annotation metadata.
  • Usage: Register the node with your Lexical editor so comment elements render correctly.
import { LexicalComposer } from '@lexical/react/LexicalComposer';
import { CommentNode } from '@veltdev/lexical-velt-comments';

const initialConfig = {
  namespace: 'MyEditor',
  nodes: [CommentNode],
  onError: console.error,
};

export default function Editor() {
  return <LexicalComposer initialConfig={initialConfig}>{/* plugins */}</LexicalComposer>;
}

addComment()

Creates a comment annotation for the currently selected text in the editor.
  • Params:
    • request: AddCommentRequest
      • editor: LexicalEditor
      • editorId?: string
      • context?: object
  • Returns: Promise<void>
import { addComment } from '@veltdev/lexical-velt-comments';

<button onClick={() => addComment({ editor, editorId: 'my-editor' })}>
  Comment
</button>

renderComments()

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

const annotations = useCommentAnnotations();

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

exportJSONWithoutComments()

Exports the editor state as serialized JSON while stripping out all comment nodes and normalizing adjacent text nodes.
  • Params: editor: LexicalEditor
  • Returns: SerializedEditorState
import { exportJSONWithoutComments } from '@veltdev/lexical-velt-comments';

const cleanState = exportJSONWithoutComments(editor);