> ## Documentation Index
> Fetch the complete documentation index at: https://docs.velt.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Tiptap Setup

<img src="https://mintcdn.com/velt/gAz_vLsG-ukKamYM/gifs/Add-Text-Comments.gif?s=1da499b73486c2acd4667b517baab389" alt="" width="1280" height="720" data-path="gifs/Add-Text-Comments.gif" />

## 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.

<Tabs>
  <Tab title="React / Next.js">
    ```js theme={null}
    <VeltProvider apiKey="API_KEY">
      <VeltComments textMode={false} />
    </VeltProvider>
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <body>
      <velt-comments text-mode="false"></velt-comments>
    </body>
    ```
  </Tab>
</Tabs>

#### Step 2: Install the Velt Tiptap extension

```bash theme={null}
npm i @veltdev/tiptap-velt-comments
```

#### Step 3: Configure the Tiptap editor with the Velt Comments extension

<Tabs>
  <Tab title="React / Next.js">
    ```js theme={null}
    import { TiptapVeltComments } from '@veltdev/tiptap-velt-comments';

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

  <Tab title="Other Frameworks">
    ```js theme={null}
    import { TiptapVeltComments } from '@veltdev/tiptap-velt-comments';

    const editor = new Editor({
      extensions: [
        TiptapVeltComments,
        // ... other extensions
      ],
    });
    ```
  </Tab>
</Tabs>

#### Step 4: Add a comment button to your Tiptap editor

Add a button in your existing bubble menu or create a new bubble menu that appears when users select text in the editor.

<Tabs>
  <Tab title="React / Next.js">
    ```js theme={null}
    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>
      );
    }
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <!-- HTML Structure -->
    <div id="editor"></div>
    <div class="bubble-menu">
      <button class="comment-button" 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"
            stroke-width="1.5"
          />
        </svg>
      </button>
    </div>
    ```

    ```js theme={null}
    import { BubbleMenu, Editor } from '@tiptap/core';
    import { addComment } from '@veltdev/tiptap-velt-comments';

    const editor = new Editor({
      element: document.querySelector('#editor'),
      // ... your editor configuration
    });

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

    // Create bubble menu
    const bubbleMenu = new BubbleMenu({
      editor,
      element: document.querySelector('.bubble-menu'),
      tippyOptions: { duration: 100 },
    });

    // Add click handler to comment button
    document.querySelector('.comment-button').addEventListener('click', (e) => {
      e.preventDefault();
      e.stopPropagation();
      addTiptapVeltComment();
    });
    ```
  </Tab>
</Tabs>

<Tip>
  Refer to the [Tiptap BubbleMenu documentation](https://tiptap.dev/docs/editor/extensions/functionality/bubble-menu) to learn more about customizing the bubble menu behavior.
</Tip>

#### 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`](/api-reference/sdk/models/data-models#addcommentrequest-1). 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](/async-collaboration/comments/customize-behavior#metadata). (optional)

<Tabs>
  <Tab title="React / Next.js">
    ```js theme={null}
    import { addComment } from '@veltdev/tiptap-velt-comments';

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

    addComment(addCommentRequest);
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    import { addComment } from '@veltdev/tiptap-velt-comments';

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

    addComment(addCommentRequest);
    ```
  </Tab>
</Tabs>

#### Step 6: Render comments in Tiptap editor

* Get the comment data from Velt SDK and render it in the Tiptap Editor.
* Params: [`RenderCommentsRequest`](/api-reference/sdk/models/data-models#rendercommentsrequest-1). 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.

<Tabs>
  <Tab title="React / Next.js">
    ```js theme={null}
    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]);
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    import { renderComments } from '@veltdev/tiptap-velt-comments';

    const commentElement = Velt.getCommentElement();
    commentElement.getAllCommentAnnotations().subscribe((annotations) => {
      if (editor && annotations?.length) {
        const renderCommentsRequest = {
          editor,
          editorId: 'EDITOR_ID',
          commentAnnotations: annotations,
        };
        renderComments(renderCommentsRequest);
      }
    });
    ```
  </Tab>
</Tabs>

#### Step 7: Persist Velt Comment Marks (optional)

* 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`

```js theme={null}
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.

```css theme={null}
velt-comment-text[comment-available="true"] {
  background-color: #ffff00;
}
```

## Complete Example

<Frame>
  <iframe src="https://documentation-app-demo.vercel.app/" className="w-full" height="500px" />
</Frame>

## APIs

#### [TiptapVeltComments.configure()](/api-reference/sdk/api/api-methods#tiptapveltcomments-configure)

A custom Tiptap extension for Velt comments.

* Params: `options?:` [TiptapVeltCommentsOptions](/api-reference/sdk/models/data-models#tiptapveltcommentsoptions)
* Returns: `TiptapVeltComments`

<Tabs>
  <Tab title="React / Next.js">
    ```tsx theme={null}
    import { useEditor } from '@tiptap/react';
    import StarterKit from '@tiptap/starter-kit';
    import { TiptapVeltComments } from '@veltdev/tiptap-velt-comments';

    const editor = useEditor({
      extensions: [
        StarterKit,
        TiptapVeltComments.configure({
          editorId: 'my-editor',
          persistVeltMarks: true,
        }),
      ],
      content: '<p>Your content</p>',
    });
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```tsx theme={null}
    import { Editor } from '@tiptap/core';
    import StarterKit from '@tiptap/starter-kit';
    import { TiptapVeltComments } from '@veltdev/tiptap-velt-comments';

    const editor = new Editor({
      element: document.querySelector('#editor'),
      extensions: [
        StarterKit,
        TiptapVeltComments.configure({
          editorId: 'my-editor',
          persistVeltMarks: true,
        }),
      ],
      content: '<p>Your content</p>',
    });
    ```
  </Tab>
</Tabs>

#### [addComment()](/api-reference/sdk/api/api-methods#addcomment-2)

Creates a comment annotation for the currently selected text in the editor.

* Params:
  * `request:` [AddCommentRequest](/api-reference/sdk/models/data-models#addcommentrequest)
    * `editor: Editor`
    * `editorId?: string`
    * `context?: object`
* Returns: `Promise<void>`

<Tabs>
  <Tab title="React / Next.js">
    ```tsx theme={null}
    import { addComment } from '@veltdev/tiptap-velt-comments';

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

  <Tab title="Other Frameworks">
    ```tsx theme={null}
    import { addComment } from '@veltdev/tiptap-velt-comments';

    addComment({
      editor,
      editorId: 'my-editor',
      context: { customData: 'value' },
    });
    ```
  </Tab>
</Tabs>

#### [renderComments()](/api-reference/sdk/api/api-methods#rendercomments-2)

Renders and highlights comment annotations in the editor.

* Params:
  * `request:` [RenderCommentsRequest](/api-reference/sdk/models/data-models#rendercommentsrequest)
    * `editor: Editor`
    * `editorId?: string`
    * `commentAnnotations?:` [CommentAnnotation\[\]](/api-reference/sdk/models/data-models#commentannotation)
* Returns: `void`

<Tabs>
  <Tab title="React / Next.js">
    ```tsx theme={null}
    import { useEffect } from 'react';
    import { renderComments } from '@veltdev/tiptap-velt-comments';
    import { useCommentAnnotations } from '@veltdev/react';

    const annotations = useCommentAnnotations();

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

  <Tab title="Other Frameworks">
    ```tsx theme={null}
    import { renderComments } from '@veltdev/tiptap-velt-comments';

    const commentElement = Velt.getCommentElement();
    commentElement.getAllCommentAnnotations().subscribe((annotations) => {
      if (editor && annotations) {
        renderComments({
          editor,
          editorId: 'my-editor',
          commentAnnotations: annotations,
        });
      }
    });
    ```
  </Tab>
</Tabs>
