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

# Customize Behavior

# Threads

#### addCommentAnnotation

* Adds a new comment annotation.
* Params: [AddCommentAnnotationRequest](/api-reference/sdk/models/data-models#addcommentannotationrequest)
* Returns: [AddCommentAnnotationEvent](/api-reference/sdk/models/data-models#addcommentannotationevent)

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentAnnotation = {
      comments: [
        {
          commentText: 'This is a comment',
          commentHtml: '<p>This is a comment</p>',
        }
      ]
    };
    const addCommentAnnotationRequest = {
      annotation: commentAnnotation
    };

    // Hook
    const { addCommentAnnotation } = useAddCommentAnnotation();
    const addCommentAnnotationEventData = await addCommentAnnotation(addCommentAnnotationRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const addCommentAnnotationEventData = await commentElement.addCommentAnnotation(addCommentAnnotationRequest);

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const commentAnnotation = {
      comments: [
        {
          commentText: 'This is a comment',
          commentHtml: '<p>This is a comment</p>',
        }
      ]
    };
    const addCommentAnnotationRequest = {
      annotation: commentAnnotation
    };

    const commentElement = Velt.getCommentElement();
    const addCommentAnnotationEventData = await commentElement.addCommentAnnotation(addCommentAnnotationRequest);
    ```
  </Tab>
</Tabs>

#### addCommentOnSelectedText

<img src="https://mintcdn.com/velt/gAz_vLsG-ukKamYM/images/addCommentOnSelectedText.png?fit=max&auto=format&n=gAz_vLsG-ukKamYM&q=85&s=b7a0b8619a4ec193ebf6ae6513d1c86e" alt="" width="1280" height="720" data-path="images/addCommentOnSelectedText.png" />

By default, when you highlight over any text in `textMode` a Comment Tool button will appear. Clicking the button will add a comment on the highlighted text.

If you want to trigger the comment using an API method call instead of clicking the button, you can do the following:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    // to add comment on selected text
    commentElement.addCommentOnSelectedText();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    // to add comment on selected text
    commentElement.addCommentOnSelectedText();
    ```
  </Tab>
</Tabs>

#### addCommentOnElement

<img src="https://mintcdn.com/velt/gAz_vLsG-ukKamYM/images/addCommentOnElement.png?fit=max&auto=format&n=gAz_vLsG-ukKamYM&q=85&s=b5b718a6fd3a45ef546d79065a95c302" alt="" width="1280" height="720" data-path="images/addCommentOnElement.png" />

Adds a Comment on a specific element by ID.

To add a comment on a specific element through an API method, use the `addCommentOnElement()` method and pass in an object with the schema shows in the example:

**Example 1: Add comment with targetElementId only:**

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const element = {
      targetElement: {
        elementId: "element_id", // optional (pass elementId if you want to add comment on a specific element)
        targetText: "target_text", // optional (pass targetText if you want to add comment on a specific text)
        occurrence: 1, // optional (default: 1) This is relevant for text comment. By default, we will attach comment to the first occurence of the target text in your document. You can change this to attach your comment on a more specific text.
        selectAllContent: true, // Set to `true` if you want to select all the text content of the target element.
      },
      commentData: [
        {
          commentText: "This is awesome! Well done.", // To set plain text content
          commentHtml:
            'This <span style="color: green; background-color: aliceblue; display: inline-block; padding: 4px; border-radius: 4px;">is test</span> comment.', // To set HTML formatted content
          replaceContentText: "This is new comment", // provide this replaceContentText to replace current text with
          replaceContentHtml: "<span>This is <b>new</b> comment.</span>", // If replacement text contains html formatted text, then provide it here
        },
      ],
      status: "open", // optional (default: open)
    };

    const commentElement = client.getCommentElement();
    commentElement.addCommentOnElement(element);
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const element = {
      targetElement: {
        elementId: "element_id", // optional (pass elementId if you want to add comment on a specific element)
        targetText: "target_text", // optional (pass targetText if you want to add comment on a specific text)
        occurrence: 1, // optional (default: 1) This is relevant for text comment. By default, we will attach comment to the first occurence of the target text in your document. You can change this to attach your comment on a more specific text.
        selectAllContent: true, // Set to `true` if you want to select all the text content of the target element.
      },
      commentData: [
        {
          commentText: "This is awesome! Well done.", // To set plain text content
          commentHtml:
            'This <span style="color: green; background-color: aliceblue; display: inline-block; padding: 4px; border-radius: 4px;">is test</span> comment.', // To set HTML formatted content
          replaceContentText: "This is new comment", // provide this replaceContentText to replace current text with
          replaceContentHtml: "<span>This is <b>new</b> comment.</span>", // If replacement text contains html formatted text, then provide it here
        },
      ],
      status: "open", // optional (default: open)
    };

    const commentElement = Velt.getCommentElement();
    commentElement.addCommentOnElement(element);
    ```
  </Tab>
</Tabs>

#### addManualComment

* This feature is particularly useful for complex UIs where you need precise control over the placement of Comment Pins.
* Using this you can manually set the position of Comment Annotations.
* Handle click events on your canvas/document and use the this method to create a comment with custom metadata.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const context = {
      position: {x: 200, y: 100},
    };
    const commentElement = client.getCommentElement();
    const config: ManualCommentAnnotationConfig = {
    	context: context, // your context here
    };
    commentElement.addManualComment(config);
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const context = {
      position: {x: 200, y: 100},
    };
    const commentElement = Velt.getCommentElement();
    const config: ManualCommentAnnotationConfig = {
    	context: context, // your context here
    };
    commentElement.addManualComment(config);
    ```
  </Tab>
</Tabs>

#### Comment and Reply Placeholders

Customize the placeholder text shown in the Comments dialog inputs to match your product voice and guide first-time users.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Using props on VeltComments
    <VeltComments commentPlaceholder="Text Comment" replyPlaceholder="Text Reply" />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comments comment-placeholder="test comment placeholder" reply-placeholder="test reply placeholder"></velt-comments>
    ```
  </Tab>
</Tabs>

#### deleteCommentAnnotation

* Deletes a comment annotation
* Params: [DeleteCommentAnnotationRequest](/api-reference/sdk/models/data-models#deletecommentannotationrequest)
* Returns: [DeleteCommentAnnotationEvent](/api-reference/sdk/models/data-models#deletecommentannotationevent)

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const deleteCommentAnnotationRequest = {
      annotationId: 'ANNOTATION_ID'
    };

    // Hook
    const { deleteCommentAnnotation } = useDeleteCommentAnnotation();
    const deleteCommentAnnotationEvent = await deleteCommentAnnotation(deleteCommentAnnotationRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const deleteCommentAnnotationEvent = await commentElement.deleteCommentAnnotation(deleteCommentAnnotationRequest);

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const deleteCommentAnnotationRequest = {
      annotationId: 'ANNOTATION_ID'
    };

    const commentElement = Velt.getCommentElement();
    const deleteCommentAnnotationEvent = await commentElement.deleteCommentAnnotation(deleteCommentAnnotationRequest);
    ```
  </Tab>
</Tabs>

#### deleteSelectedComment

To delete a comment using an API method, use the `deleteSelectedComment()` method.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    if (client) {
      const commentElement = client.getCommentElement();
      commentElement.deleteSelectedComment();
    }
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    if (Velt) {
      const commentElement = Velt.getCommentElement();
      commentElement.deleteSelectedComment();
    }
    ```
  </Tab>
</Tabs>

### [getCommentAnnotationsCount](/api-reference/sdk/api/api-methods#getcommentannotationscount)

* Get the total and unread comment annotations count of all the comment annotations across specified Organization, Folder, Document and Multiple Documents levels.
* If you don't specify any query, it will return data from the folder/documents specified in the `setDocuments` method.
* You can also use this api without setting the document.
* **Auto-batching:** When 2+ `documentIds` are provided, requests are automatically batched to reduce persistence listeners. Use `debounceMs` to control batching delay (default: 5000ms).
* **Params:** (optional) [CommentRequestQuery](/api-reference/sdk/models/data-models#commentrequestquery)
  * Set `aggregateDocuments` to `true` to aggregate comment counts across all documents set in the `setDocuments` method, returning a single combined count instead of per-document counts.
  * Set `batchedPerDocument` to `true` if you want to display comment count for a large number of documents (e.g., 100 documents) on the same page. This is now automatically enabled when 2+ `documentIds` are provided.
  * Refer to [CommentRequestQuery](/api-reference/sdk/models/data-models#commentrequestquery) for more parameters you can use.
* **Returns:** [GetCommentAnnotationsCountResponse](/api-reference/sdk/models/data-models#getcommentannotationscountresponse)

<Tabs>
  <Tab title="React / Next.js">
    <CodeGroup>
      ```jsx Organization Level theme={null}
      const { data } = useCommentAnnotationsCount({ organizationId: 'org1' });

      useEffect(() => {
      if (data) {
      console.log('Comment annotations count for org1:', data);
      }
      }, [data]);

      ```

      ```jsx Folder Level theme={null}
      const { data } = useCommentAnnotationsCount({
        organizationId: 'org1',
        folderId: 'folder2',
        allDocuments: true
      });

      useEffect(() => {
        if (data) {
          console.log('Comment annotations count for folder2:', data);
        }
      }, [data]);
      ```

      ```jsx Document Level (Default) theme={null}
      const { data } = useCommentAnnotationsCount();

      useEffect(() => {
        if (data) {
          console.log("Comment annotations count:", data);
        }
      }, [data]);
      ```

      ```jsx Multiple Documents (auto-batched) theme={null}
      const { data } = useCommentAnnotationsCount({
        documentIds: ["doc1", "doc2", "doc3"],
      });

      useEffect(() => {
        if (data) {
          // Auto-batching reduces listeners from 3 to 1 for this example
          console.log("Comment annotations count for multiple documents:", data);
        }
      }, [data]);
      ```

      ```jsx Aggregate Documents theme={null}
      const { data } = useCommentAnnotationsCount({ aggregateDocuments: true });

      useEffect(() => {
        if (data) {
          console.log("Aggregated comment annotations count:", data);
        }
      }, [data]);
      ```

      ```jsx Aggregate Multiple Documents (auto-batched) theme={null}
      const { data } = useCommentAnnotationsCount({
        documentIds: ["doc1", "doc2", "doc3"],
        aggregateDocuments: true,
      });

      useEffect(() => {
        if (data) {
          // Auto-batching reduces listeners from 3 to 1 for this example
          console.log(
            "Aggregated comment annotations count for multiple documents:",
            data,
          );
        }
      }, [data]);
      ```

      ```jsx Filter out Ghost Comments theme={null}
      const { data } = useCommentAnnotationsCount({ filterGhostComments: true });

      useEffect(() => {
        if (data) {
          console.log("Filtered comment annotations count:", data);
        }
      }, [data]);
      ```

      ```jsx Custom Debounce for Auto-batching theme={null}
      const { data } = useCommentAnnotationsCount({
        documentIds: ["doc1", "doc2", "doc3"],
        debounceMs: 3000, // customize debounce (default is 5000ms)
      });

      useEffect(() => {
        if (data) {
          // Auto-batching reduces listeners from 3 to 1 for this example
          // Custom debounce triggers updates faster (3s instead of default 5s)
          console.log("Comment annotations count with custom debounce:", data);
        }
      }, [data]);
      ```
    </CodeGroup>

    **Using API:**

    <CodeGroup>
      ```jsx Organization Level theme={null}
      const commentElement = client.getCommentElement();
      commentElement.getCommentAnnotationsCount({ organizationId: 'org1' }).subscribe((response) => {
        console.log('getCommentAnnotationsCount with organizationId', response.data);
      });
      ```

      ```jsx Folder Level theme={null}
      const commentElement = client.getCommentElement();
      commentElement
        .getCommentAnnotationsCount({
          organizationId: "org1",
          folderId: "folder2",
          allDocuments: true,
        })
        .subscribe((response) => {
          console.log(
            "getCommentAnnotationsCount with organizationId and folderId and allDocuments",
            response.data,
          );
        });
      ```

      ```jsx Document Level (Default) theme={null}
      const commentElement = client.getCommentElement();
      commentElement.getCommentAnnotationsCount().subscribe((response) => {
        console.log("getCommentAnnotationsCount", response.data);
      });
      ```

      ```jsx Multiple Documents (auto-batched) theme={null}
      const commentElement = client.getCommentElement();
      commentElement
        .getCommentAnnotationsCount({
          documentIds: ["doc1", "doc2", "doc3"],
        })
        .subscribe((response) => {
          // Auto-batching reduces listeners from 3 to 1 for this example
          console.log(
            "getCommentAnnotationsCount for multiple documents",
            response.data,
          );
        });
      ```

      ```jsx Aggregate Documents theme={null}
      const commentElement = client.getCommentElement();
      commentElement
        .getCommentAnnotationsCount({ aggregateDocuments: true })
        .subscribe((response) => {
          console.log(
            "getCommentAnnotationsCount with aggregateDocuments",
            response.data,
          );
        });
      ```

      ```jsx Aggregate Multiple Documents (auto-batched) theme={null}
      const commentElement = client.getCommentElement();
      commentElement
        .getCommentAnnotationsCount({
          documentIds: ["doc1", "doc2", "doc3"],
          aggregateDocuments: true,
        })
        .subscribe((response) => {
          // Auto-batching reduces listeners from 3 to 1 for this example
          console.log(
            "getCommentAnnotationsCount for aggregated multiple documents",
            response.data,
          );
        });
      ```

      ```jsx Filter out Ghost Comments theme={null}
      const commentElement = client.getCommentElement();
      commentElement
        .getCommentAnnotationsCount({ filterGhostComments: true })
        .subscribe((response) => {
          console.log(
            "getCommentAnnotationsCount with filterGhostComments",
            response.data,
          );
        });
      ```

      ```jsx Custom Debounce for Auto-batching theme={null}
      const commentElement = client.getCommentElement();
      commentElement
        .getCommentAnnotationsCount({
          documentIds: ["doc1", "doc2", "doc3"],
          debounceMs: 3000, // customize debounce (default is 5000ms)
        })
        .subscribe((response) => {
          // Auto-batching reduces listeners from 3 to 1 for this example
          // Custom debounce triggers updates faster (3s instead of default 5s)
          console.log(
            "Comment annotations count with custom debounce:",
            response.data,
          );
        });
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Other Frameworks">
    <CodeGroup>
      ```js Organization Level theme={null}
      const commentElement = Velt.getCommentElement();
      commentElement.getCommentAnnotationsCount({ organizationId: 'org1' }).subscribe((response) => {
        console.log('getCommentAnnotationsCount with organizationId', response.data);
      });
      ```

      ```js Folder Level theme={null}
      const commentElement = Velt.getCommentElement();
      commentElement
        .getCommentAnnotationsCount({
          organizationId: "org1",
          folderId: "folder2",
          allDocuments: true,
        })
        .subscribe((response) => {
          console.log(
            "getCommentAnnotationsCount with organizationId and folderId and allDocuments",
            response.data,
          );
        });
      ```

      ```js Document Level (Default) theme={null}
      const commentElement = Velt.getCommentElement();
      commentElement.getCommentAnnotationsCount().subscribe((response) => {
        console.log("getCommentAnnotationsCount", response.data);
      });
      ```

      ```js Multiple Documents (auto-batched) theme={null}
      const commentElement = Velt.getCommentElement();
      commentElement
        .getCommentAnnotationsCount({
          documentIds: ["doc1", "doc2", "doc3"],
        })
        .subscribe((response) => {
          // Auto-batching reduces listeners from 3 to 1 for this example
          console.log(
            "getCommentAnnotationsCount for multiple documents",
            response.data,
          );
        });
      ```

      ```js Aggregate Documents theme={null}
      const commentElement = Velt.getCommentElement();
      commentElement
        .getCommentAnnotationsCount({ aggregateDocuments: true })
        .subscribe((response) => {
          console.log(
            "getCommentAnnotationsCount with aggregateDocuments",
            response.data,
          );
        });
      ```

      ```js Filter Ghost Comments theme={null}
      const commentElement = Velt.getCommentElement();
      commentElement
        .getCommentAnnotationsCount({ filterGhostComments: true })
        .subscribe((response) => {
          console.log(
            "getCommentAnnotationsCount with filterGhostComments",
            response.data,
          );
        });
      ```

      ```js Custom Debounce for Auto-batching theme={null}
      const commentElement = Velt.getCommentElement();
      commentElement
        .getCommentAnnotationsCount({
          documentIds: ["doc1", "doc2", "doc3"],
          debounceMs: 3000, // customize debounce (default is 5000ms)
        })
        .subscribe((response) => {
          // Auto-batching reduces listeners from 3 to 1 for this example
          // Custom debounce triggers updates faster (3s instead of default 5s)
          console.log(
            "Comment annotations count with custom debounce:",
            response.data,
          );
        });
      ```
    </CodeGroup>
  </Tab>
</Tabs>

#### getUnreadCommentAnnotationCountByLocationId

* Get the number of `CommentAnnotations` with at least 1 unread Comment by Location Id.

<Tabs>
  <Tab title="React / Next.js">
    **Using Hooks:**

    ```jsx theme={null}
    const count = useUnreadCommentAnnotationCountByLocationId(locationId);
    useEffect(() => {
      console.log(count, "countObj");
    }, [count]);
    ```

    **Using API:**

    ```jsx theme={null}
    if (client) {
      const commentElement = client.getCommentElement();
      let subscription = commentElement
        .getUnreadCommentAnnotationCountByLocationId(locationId)
        .subscribe((countObj) => {
          console.log(countObj);
        });
    }
    ```

    To unsubscribe from the subscription:

    ```jsx theme={null}
    subscription?.unsubscribe();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    if (Velt) {
      const commentElement = Velt.getCommentElement();
      let subscription = commentElement
        .getUnreadCommentAnnotationCountByLocationId(locationId)
        .subscribe((countObj) => {
          console.log(countObj);
        });
    }
    ```

    To unsubscribe from the subscription:

    ```jsx theme={null}
    subscription?.unsubscribe();
    ```
  </Tab>
</Tabs>

#### getCommentAnnotations

* Subscribe to the comment annotations for all the specified documents.
* If you don't specify any query, it will return data from the currently set `documents` and `locations`.
* You can specify 30 documents at a time.
* **Params:** (optional) [CommentRequestQuery](/api-reference/sdk/models/data-models#commentrequestquery)
* **Returns:** [GetCommentAnnotationsResponse](/api-reference/sdk/models/data-models#getcommentannotationsresponse)

<Info>
  Available on SDK version 4.0.0 and above.
</Info>

<Tabs>
  <Tab title="React / Next.js">
    **Using Hooks:**

    ```jsx theme={null}
    const { data } = useGetCommentAnnotations(query);

    useEffect(() => {
      if (data) {
        // initial data value will be null while the request is in progress
        console.log("Comment Annotations:", data);
      }
    }, [data]);
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.getCommentAnnotations(query).subscribe((response) => {
      // initial data value will be null while the request is in progress
      console.log("Comment Annotations:", response.data);
    });
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using API:**

    ```js theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.getCommentAnnotations(query).subscribe((response) => {
      // initial data value will be null while the request is in progress
      console.log("Comment Annotations:", response.data);
    });
    ```
  </Tab>
</Tabs>

#### fetchCommentAnnotations

* Fetches comment annotations based on various criteria such as organizationId, folderId, or specific documentIds.
* It supports pagination and filtering options.
* This is different from the existing subscription API which susbcribes to realtime changes to the comments data.
* Params: [FetchCommentAnnotationsRequest](/api-reference/sdk/models/data-models#fetchcommentannotationsrequest)
* Returns: [FetchCommentAnnotationsResponse](/api-reference/sdk/models/data-models#fetchcommentannotationsresponse)

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Get all annotations for a specific folder
    const commentElement = client.getCommentElement();
    const response = await commentElement.fetchCommentAnnotations({
      organizationId: 'org1', 
      folderId: 'folder1',
      allDocuments: true
    });

    // Get annotations for specific documents
    const response = await commentElement.fetchCommentAnnotations({
    organizationId: 'org1',
    documentIds: ['doc1', 'doc2']
    });

    // Get annotations with filters
    const response = await commentElement.fetchCommentAnnotations({
    organizationId: 'org1',
    documentIds: ['doc1', 'doc2'],
    createdAfter: 1234567890,
    statusIds: ['open'],
    pageSize: 20
    });

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    // Get all annotations for a specific folder
    const commentElement = Velt.getCommentElement();
    const response = await commentElement.fetchCommentAnnotations({
      organizationId: 'org1',
      folderId: 'folder1',
      allDocuments: true
    });

    // Get annotations for specific documents
    const response = await commentElement.fetchCommentAnnotations({
      organizationId: 'org1',
      documentIds: ['doc1', 'doc2']
    });

    // Get annotations with filters
    const response = await commentElement.fetchCommentAnnotations({
      organizationId: 'org1',
      documentIds: ['doc1', 'doc2'],
      createdAfter: 1234567890,
      statusIds: ['open'],
      pageSize: 20
    });
    ```
  </Tab>
</Tabs>

#### getSelectedComments

* Get the currently selected comment annotations.
* Returns: [`CommentAnnotation[]`](/api-reference/sdk/models/data-models#commentannotation).

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    const subscription = commentElement
      .getSelectedComments()
      .subscribe((selectedComments) => {
        console.log("Selected comments:", selectedComments);
      });
    ```

    Unsubscribe from the subscription when you're done:

    ```jsx theme={null}
    subscription?.unsubscribe();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const commentElement = Velt.getCommentElement();
    const subscription = commentElement
      .getSelectedComments()
      .subscribe((selectedComments) => {
        console.log("Selected comments:", selectedComments);
      });
    ```

    Unsubscribe from the subscription when you're done:

    ```js theme={null}
    subscription?.unsubscribe();
    ```
  </Tab>
</Tabs>

#### getCommentAnnotationById

* Retrieve a specific comment annotation by its ID.
* By default, it will return the comment annotation for the current `documentId`.
* If you pass in a `documentId`, it will return the comment annotation for the given `documentId`.
* Returns: [CommentAnnotation](/api-reference/sdk/models/data-models#commentannotation)

<Tabs>
  <Tab title="React / Next.js">
    **Using Hooks:**

    ```jsx theme={null}
    const annotation = useCommentAnnotationById({
      annotationId: '-O6W3jD0Lz3rxuDuqQFx',  // AnnotationID
      documentId: 'document-id'              // DocumentId (Optional)
    });

    useEffect(() => {
      console.log('annotation', annotation);
    }, [annotation]);
    ```

    **Using API:**

    ```javascript theme={null}
    const commentElement = client.getCommentElement();

        let subscription = commentElement.getCommentAnnotationById({
          annotationId: '-O6W3jD0Lz3rxuDuqQFx',  // AnnotationID
          documentId: 'document-id'              // DocumentId (Optional)
        }).subscribe((annotation) => {
          console.log('annotation', annotation);
        });
    ```

    To unsubscribe from the subscription:

    ```jsx theme={null}
    subscription?.unsubscribe()
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using API:**

    ```javascript theme={null}
    const commentElement = Velt.getCommentElement();

    let subscription = commentElement.getCommentAnnotationById({
      annotationId: '-O6W3jD0Lz3rxuDuqQFx',  // AnnotationID
      documentId: 'document-id'              // DocumentId (Optional)
    }).subscribe((annotation) => {
      console.log('annotation', annotation);
    });
    ```

    To unsubscribe from the subscription:

    ```jsx theme={null}
    subscription?.unsubscribe()
    ```
  </Tab>
</Tabs>

#### getElementRefByAnnotationId

This will return the Xpath of the DOM element on which the comment was added.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    let elementRef = commentElement.getElementRefByAnnotationId("annotationId");
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    let elementRef = commentElement.getElementRefByAnnotationId('annotationId')
    ```
  </Tab>
</Tabs>

#### submitComment

Programmatically submit a comment from a composer. Enables custom buttons or keyboard shortcuts for submitting comments. The composer must have a `targetComposerElementId` set for this method to work.

* Params: [`SubmitCommentRequest`](/api-reference/sdk/models/data-models#submitcommentrequest)
* Returns: `void`
* See also: [Comment Composer targetComposerElementId](/ui-customization/features/async/comments/standalone-components/comment-composer#target-composer-element-id)

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}

    <VeltCommentComposer targetComposerElementId="composer-1" />
    <VeltCommentDialogComposer targetComposerElementId="composer-2" />

    // Using hook
    const commentElement = useCommentUtils();
    commentElement.submitComment({ targetComposerElementId: 'composer-1' });

    // Using API method
    const client = useVeltClient();
    const commentElement = client.getCommentElement();
    commentElement.submitComment({ targetComposerElementId: 'composer-1' });

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.submitComment({ targetComposerElementId: 'composer-1' });
    ```
  </Tab>
</Tabs>

#### clearComposer

Reset composer state including text, attachments, recordings, tagged users, assignments, and custom lists.

* Params: [`ClearComposerRequest`](/api-reference/sdk/models/data-models#clearcomposerrequest)
* Returns: `void`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Hook
    const commentElement = useCommentUtils();
    commentElement.clearComposer({ targetComposerElementId: "composer-1" });

    // API Method
    const commentElement = client.getCommentElement();
    commentElement.clearComposer({ targetComposerElementId: "composer-1" });
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.clearComposer({ targetComposerElementId: 'composer-1' });
    ```
  </Tab>
</Tabs>

#### getComposerData

Fetch current composer state on-demand. Returns same data structure as composerTextChange event.

* Params: [`GetComposerDataRequest`](/api-reference/sdk/models/data-models#getcomposerdatarequest)
* Returns: [`ComposerTextChangeEvent`](/api-reference/sdk/models/data-models#composertextchangeevent)

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Hook
    const commentElement = useCommentUtils();
    const composerData = commentElement.getComposerData({
      targetComposerElementId: "composer-1",
    });

    // API Method
    const commentElement = client.getCommentElement();
    const composerData = commentElement.getComposerData({
      targetComposerElementId: "composer-1",
    });
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const commentElement = Velt.getCommentElement();
    const composerData = commentElement.getComposerData({
      targetComposerElementId: 'composer-1'
    });
    ```
  </Tab>
</Tabs>

#### markAsRead

* Mark a comment annotation as read for the current user. This updates the `viewedBy` field of the comment annotation to include the current user.
* Params: `annotationId: string`
* Returns: `Promise<void>`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const markAsReadRequest = {
      annotationId: "ANNOTATION_ID",
    };

    // Hook
    const { markAsRead } = useCommentUtils();
    await markAsRead(markAsReadRequest);

    // API Method
    const commentElement = client.getCommentElement();
    await commentElement.markAsRead(markAsReadRequest);
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const markAsReadRequest = {
      annotationId: "ANNOTATION_ID",
    };

    const commentElement = Velt.getCommentElement();
    await commentElement.markAsRead(markAsReadRequest);
    ```
  </Tab>
</Tabs>

#### markAsUnread

* Mark a comment annotation as unread for the current user. This removes the current user from the `viewedBy` field of the comment annotation.
* Params: `annotationId: string`
* Returns: `Promise<void>`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const markAsUnreadRequest = {
      annotationId: "ANNOTATION_ID",
    };

    // Hook
    const { markAsUnread } = useCommentUtils();
    await markAsUnread(markAsUnreadRequest);

    // API Method
    const commentElement = client.getCommentElement();
    await commentElement.markAsUnread(markAsUnreadRequest);
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const markAsUnreadRequest = {
      annotationId: "ANNOTATION_ID",
    };

    const commentElement = Velt.getCommentElement();
    await commentElement.markAsUnread(markAsUnreadRequest);
    ```
  </Tab>
</Tabs>

# Messages

#### addComment

* Add a comment to a specific comment annotation
* Params: [AddCommentRequest](/api-reference/sdk/models/data-models#addcommentrequest)
* Returns: [AddCommentEvent](/api-reference/sdk/models/data-models#addcommentevent)

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const comment = {
        commentText: 'This is a comment',
        commentHtml: '<p>This is a comment</p>',
    };

    const addCommentRequest = {
    annotationId: 'ANNOTATION_ID',
    comment: comment
    };

    // Hook
    const { addComment } = useAddComment();
    const addCommentEventData = await addComment(addCommentRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const addCommentEventData = await commentElement.addComment(addCommentRequest);

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const comment = {
        commentText: 'This is a comment',
        commentHtml: '<p>This is a comment</p>',
    };

    const addCommentRequest = {
      annotationId: 'ANNOTATION_ID',
      comment: comment
    };

    const commentElement = Velt.getCommentElement();
    const addCommentEventData = await commentElement.addComment(addCommentRequest);
    ```
  </Tab>
</Tabs>

#### updateComment

* Update a comment in a specific comment annotation
* Params: [UpdateCommentRequest](/api-reference/sdk/models/data-models#updatecommentrequest)
* Returns: [UpdateCommentEvent](/api-reference/sdk/models/data-models#updatecommentevent)

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const comment = {
    		commentId: 'COMMENT_ID',
        commentText: 'This is a comment',
        commentHtml: '<p>This is a comment</p>',
    };

    const updateCommentRequest = {
    annotationId: 'ANNOTATION_ID',
    comment: comment
    };

    // Hook
    const { updateComment } = useUpdateComment();
    const updateCommentEvent = await updateComment(updateCommentRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const updateCommentEvent = await commentElement.updateComment(updateCommentRequest);

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const comment = {
    		commentId: 'COMMENT_ID',
        commentText: 'This is a comment',
        commentHtml: '<p>This is a comment</p>',
    };

    const updateCommentRequest = {
      annotationId: 'ANNOTATION_ID',
      comment: comment
    };

    const commentElement = Velt.getCommentElement();
    const updateCommentEvent = await commentElement.updateComment(updateCommentRequest);
    ```
  </Tab>
</Tabs>

#### deleteComment

* Delete a comment from a specific comment annotation
* Params: [DeleteCommentRequest](/api-reference/sdk/models/data-models#deletecommentrequest)
* Returns: [DeleteCommentEvent](/api-reference/sdk/models/data-models#deletecommentevent)

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const deleteCommentRequest = {
      annotationId: 'ANNOTATION_ID',
      commentId: COMMENT_ID
    };

    // Hook
    const { deleteComment } = useDeleteComment();
    const deleteCommentEvent = await deleteComment(deleteCommentRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const deleteCommentEvent = await commentElement.deleteComment(deleteCommentRequest);

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const deleteCommentRequest = {
      annotationId: 'ANNOTATION_ID',
      commentId: COMMENT_ID
    };

    const commentElement = Velt.getCommentElement();
    const deleteCommentEvent = await commentElement.deleteComment(deleteCommentRequest);
    ```
  </Tab>
</Tabs>

#### getComment

* Get comments from a specific comment annotation
* Params: [GetCommentRequest](/api-reference/sdk/models/data-models#getcommentrequest)
* Returns: [Comment\[\]](/api-reference/sdk/models/data-models#comment)

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const getCommentRequest = {
      annotationId: 'ANNOTATION_ID'
    };

    // Hook
    const { getComment } = useGetComment();
    const comments = await getComment(getCommentRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const comments = await commentElement.getComment(getCommentRequest);

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const getCommentRequest = {
      annotationId: 'ANNOTATION_ID'
    };

    const commentElement = Velt.getCommentElement();
    const comments = await commentElement.getComment(getCommentRequest);
    ```
  </Tab>
</Tabs>

#### getUnreadCommentCountOnCurrentDocument

<Tabs>
  <Tab title="React / Next.js with Hooks">
    You can get the number of unread `Comments` on the current `Document` by using the `useUnreadCommentCountOnCurrentDocument()` hook:

    ```jsx theme={null}
    const count = useUnreadCommentCountOnCurrentDocument();
    useEffect(() => {
      console.log(count, "countObj");
    }, [count]);
    ```
  </Tab>

  <Tab title="React / Next.js">
    You can get the number of unread `Comments` on the current `Document` by using the `getUnreadCommentCountOnCurrentDocument()` method:

    ```jsx theme={null}
    if (client) {
      const commentElement = client.getCommentElement();
      let subscription = commentElement
        .getUnreadCommentCountOnCurrentDocument()
        .subscribe((countObj) => {
          console.log(countObj);
        });
    }
    ```

    To unsubscribe from the subscription:

    ```jsx theme={null}
    subscription?.unsubscribe();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    You can get the number of unread `Comments` on the current `Document` by using the `getUnreadCommentCountOnCurrentDocument()` method:

    ```jsx theme={null}
    if (Velt) {
      const commentElement = Velt.getCommentElement();
      let subscription = commentElement
        .getUnreadCommentCountOnCurrentDocument()
        .subscribe((countObj) => {
          console.log(countObj);
        });
    }
    ```

    To unsubscribe from the subscription:

    ```jsx theme={null}
    subscription?.unsubscribe();
    ```
  </Tab>
</Tabs>

#### getUnreadCommentCountByLocationId

<Tabs>
  <Tab title="React / Next.js with Hooks">
    You can get the number of unread `Comments` by `Location Id` by using the `useUnreadCommentCountByLocationId()` hook:

    ```jsx theme={null}
    const count = useUnreadCommentCountByLocationId(locationId);
    useEffect(() => {
      console.log(count, "countObj");
    }, [count]);
    ```
  </Tab>

  <Tab title="React / Next.js">
    You can get the number of unread `Comments` by `Location Id` by using the `getUnreadCommentCountByLocationId()` method:

    ```jsx theme={null}
    if (client) {
      const commentElement = client.getCommentElement();
      let subscription = commentElement
        .getUnreadCommentCountByLocationId(locationId)
        .subscribe((countObj) => {
          console.log(countObj);
        });
    }
    ```

    To unsubscribe from the subscription:

    ```jsx theme={null}
    subscription?.unsubscribe();
    ```
  </Tab>

  <Tab title="React / HTML">
    You can get the number of unread `Comments` by `Location Id` by using the `getUnreadCommentCountByLocationId()` method:

    ```jsx theme={null}
    if (Velt) {
      const commentElement = Velt.getCommentElement();
      let subscription = commentElement
        .getUnreadCommentCountByLocationId(locationId)
        .subscribe((countObj) => {
          console.log(countObj);
        });
    }
    ```

    To unsubscribe from the subscription:

    ```jsx theme={null}
    subscription?.unsubscribe();
    ```
  </Tab>
</Tabs>

#### getUnreadCommentCountByAnnotationId

<Tabs>
  <Tab title="React / Next.js with Hooks">
    You can get the number of unread `Comments` by annotation id by using the `useUnreadCommentCountByAnnotationId()` hook:

    ```jsx theme={null}
    const count = useUnreadCommentCountByAnnotationId(annotationId);
    useEffect(() => {
      console.log(count, "countObj");
    }, [count]);
    ```
  </Tab>

  <Tab title="React / Next.js">
    You can get the number of unread `Comments` by annotation id by subscribing to the `getUnreadCommentCountByAnnotationId()` method:

    ```jsx theme={null}
    if (client) {
      const commentElement = client.getCommentElement();
      let subscription = commentElement
        .getUnreadCommentCountByAnnotationId(annotationId)
        .subscribe((countObj) => {
          console.log(countObj);
        });
    }
    ```

    To unsubscribe from the subscription:

    ```jsx theme={null}
    subscription?.unsubscribe();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    You can get the number of unread `Comments` by annotation id by subscribing to the `getUnreadCommentCountByAnnotationId()` method:

    ```jsx theme={null}
    if (Velt) {
      const commentElement = Velt.getCommentElement();
      let subscription = commentElement
        .getUnreadCommentCountByAnnotationId(annotationId)
        .subscribe((countObj) => {
          console.log(countObj);
        });
    }
    ```

    To unsubscribe from the subscription:

    ```jsx theme={null}
    subscription?.unsubscribe();
    ```
  </Tab>
</Tabs>

# @Mentions

#### assignUser

* Assigns a user to a comment annotation
* Params: [AssignUserRequest](/api-reference/sdk/models/data-models#assignuserrequest)
* Returns: [AssignUserEvent](/api-reference/sdk/models/data-models#assignuserevent)

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const assignUserRequest = {
      annotationId: 'ANNOTATION_ID',
      assignedTo: {
        userId: 'USER_ID',
        name: 'USER_NAME',
        email: 'USER_EMAIL'
      }
    };

    // Hook
    const { assignUser } = useAssignUser();
    const assignUserEventData = await assignUser(assignUserRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const assignUserEventData = await commentElement.assignUser(assignUserRequest);

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const assignUserRequest = {
      annotationId: 'ANNOTATION_ID',
      assignedTo: {
        userId: 'USER_ID',
        name: 'USER_NAME',
        email: 'USER_EMAIL'
      }
    };

    const commentElement = Velt.getCommentElement();
    const assignUserEventData = await commentElement.assignUser(assignUserRequest);
    ```
  </Tab>
</Tabs>

#### setAssignToType

Configure the assign-to UI mode as dropdown or checkbox.

API Method: [`setAssignToType()`](/api-reference/sdk/api/api-methods#setassigntotype)

* Params: [`AssignToConfig`](/api-reference/sdk/models/data-models#assigntoconfig)
* Returns: `void`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Using props
    <VeltComments assignToType="checkbox" />

    // Using API methods
    const commentElement = useCommentUtils();
    commentElement.setAssignToType({ type: 'checkbox' }); // or 'dropdown'

    // Using API methods with client
    const commentElement = client.getCommentElement();
    commentElement.setAssignToType({ type: 'checkbox' }); // or 'dropdown'

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comments assign-to-type="checkbox"></velt-comments>

    <script>
    const commentElement = Velt.getCommentElement();
    commentElement.setAssignToType({ type: 'checkbox' }); // or 'dropdown'
    </script>
    ```
  </Tab>
</Tabs>

#### customAutocompleteSearch

* Handle autocomplete search for @mentions. You should use this if you have a large contact list that you want to plug into the autocomplete dropdown, and search directly your own data source.
* Event: [`AutocompleteSearchEvent`](/api-reference/sdk/models/data-models#autocompletesearchevent)

<Tabs>
  <Tab title="React / Next.js">
    <Steps>
      <Step title="Enable the feature">
        ```jsx theme={null}
        // Enable via props
        <VeltComments customAutocompleteSearch={true} />

        // Or, enable via Comment Element API
        const commentElement = client.getCommentElement();
        commentElement.enableCustomAutocompleteSearch();
        commentElement.disableCustomAutocompleteSearch();

        ```
      </Step>

      <Step title="Set initial list">
        ```jsx theme={null}
        contactElement.updateContactList(users);
        ```
      </Step>

      <Step title="Handle search event">
        ```jsx theme={null}
        commentElement.on('autocompleteSearch').subscribe(async (inputData) => {
            const searchText = inputData.searchText;

            if (inputData.type === 'contact') {
                const filteredUsersData = await __your_api_call__(searchText);
                contactElement.updateContactList(filteredUsersData, { merge: false });
            }

        });

        ```
      </Step>
    </Steps>
  </Tab>

  <Tab title="Other Frameworks">
    <Steps>
      <Step title="Enable the feature">
        ```js theme={null}
        // Enable via attribute
        <velt-comments custom-autocomplete-search="true"></velt-comments>

        // Or, enable via Comment Element API
        const commentElement = Velt.getCommentElement();
        commentElement.enableCustomAutocompleteSearch();
        commentElement.disableCustomAutocompleteSearch();
        ```
      </Step>

      <Step title="Set initial list">
        ```js theme={null}
        contactElement.updateContactList(users);
        ```
      </Step>

      <Step title="Handle search event">
        ```js theme={null}
        commentElement.on('autocompleteSearch').subscribe(async (inputData) => {
            const searchText = inputData.searchText;

            if (inputData.type === 'contact') {
                const filteredUsersData = await __your_api_call__(searchText);
                contactElement.updateContactList(filteredUsersData, { merge: false });
            }

        });

        ```
      </Step>
    </Steps>
  </Tab>
</Tabs>

#### enableAtHere

* This allows you to notify all the users explicitly added to the current document.
* It won't notify users in the organization who are not explicitly added to the document.

Default: Disabled.

<img src="https://mintcdn.com/velt/gAz_vLsG-ukKamYM/gifs/enable-@-here.png?fit=max&auto=format&n=gAz_vLsG-ukKamYM&q=85&s=9adf0fac21313b3e73a0ee990a6c3330" alt="" width="2560" height="1440" data-path="gifs/enable-@-here.png" />

<Tabs>
  <Tab title="React / Next.js">
    **Hooks:**

    ```jsx theme={null}
    const contactElement = useContactUtils();

    useEffect(() => {
      contactElement.enableAtHere();
      contactElement.disableAtHere();
    }, [contactElement]);

    ```

    **API:**

    ```jsx theme={null}
    const contactElement = client.getContactElement();
    contactElement.enableAtHere();
    contactElement.disableAtHere();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const contactElement = Velt.getContactElement();
    contactElement.enableAtHere();
    contactElement.disableAtHere();
    ```
  </Tab>
</Tabs>

#### enableUserMentions

* This allows you to enable or disable user @mentions.

Whether user @mentions are enabled.

`Default: true`

<Tabs>
  <Tab title="React / Next.js">
    Using Props:

    ```jsx theme={null}
    <VeltComments userMentions={false} />
    ```

    **Using Hooks:**

    ```jsx theme={null}
    const contactElement = useContactUtils();

    useEffect(() => {
      contactElement.enableUserMentions();
      contactElement.disableUserMentions();
    }, [contactElement]);
    ```

    **Using API Method:**

    ```jsx theme={null}
    const contactElement = client.getContactElement();
    contactElement.enableUserMentions();
    contactElement.disableUserMentions();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using props:**

    ```jsx theme={null}
    <velt-comments user-mentions="false"></velt-comments>
    ```

    **Using API Method:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableUserMentions(); // to enable user mentions
    commentElement.disableUserMentions(); // to disable user mentions
    ```
  </Tab>
</Tabs>

#### enablePaginatedContactList

* Limits users downloaded for customers with thousands of users.
* Performance optimization that reduces initial download.

`Default: false`

<Tabs>
  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments paginatedContactList={true} />
    ```

    **Using API Method:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enablePaginatedContactList();
    commentElement.disablePaginatedContactList();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using HTML Attribute:**

    ```html theme={null}
    <velt-comments paginated-contact-list="true"></velt-comments>
    ```

    **Using API Method:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enablePaginatedContactList();
    commentElement.disablePaginatedContactList();
    ```
  </Tab>
</Tabs>

#### anonymousEmail

* Controls whether unrecognized email addresses (not in the contact list) are resolved in the @mention flow.
* When disabled:
  * Freeform email addresses entered in the composer are ignored: they won’t show up in @mention suggestions, won’t be added to `taggedUserContacts`, and won’t be converted to contacts. However, known contacts (users matched from your contact list by email) will always appear, no matter this setting.
  * Notifications will not be sent to anonymous (unrecognized) email addresses.

`Default: true`

<Tabs>
  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments anonymousEmail={false} />
    <VeltInlineCommentsSection anonymousEmail={false} />
    <VeltCommentDialog anonymousEmail={false} />
    ```

    **Using API Method:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableAnonymousEmail();
    commentElement.disableAnonymousEmail();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using HTML Attribute:**

    ```html theme={null}
    <velt-comments anonymous-email="false"></velt-comments>
    <velt-inline-comments-section target-element-id="article-body" anonymous-email="false"></velt-inline-comments-section>
    <velt-comment-dialog anonymous-email="false"></velt-comment-dialog>
    ```

    **Using API Method:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableAnonymousEmail();
    commentElement.disableAnonymousEmail();
    ```
  </Tab>
</Tabs>

#### expandMentionGroups

* Expand the user groups and show individual users inside the groups in the @mentions dropdown menu.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments expandMentionGroups={true} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comments expand-mention-groups="true"></velt-comments>
    ```
  </Tab>
</Tabs>

#### Mention Span CSS Classes

* When a user selects an @mention from the autocomplete dropdown, the inserted `<span>` element receives CSS classes that indicate the mention type.
* `velt-mention` is always present on every mention span.
* `velt-mention--name` is added when the mention is a user name.
* `velt-mention--email` is added when the mention is an email address.

Use these classes to apply distinct visual treatments to name vs. email mentions in the composer:

```css theme={null}
.velt-mention {
  font-weight: 600;
}
.velt-mention--name {
  color: #1a73e8;
}
.velt-mention--email {
  color: #7c3aed;
}
```

#### getContactList

* Subscribe to the list of users added to organization, folder, document, user groups or the ones overwritten using the `updateContactList` API.
* **Params:** none
* **Returns:** [GetContactListResponse](/api-reference/sdk/models/data-models#getcontactlistresponse)

<Tabs>
  <Tab title="React / Next.js">
    **Using Hooks:**

    ```jsx theme={null}
    const contactList = useContactList();
    console.log(contactList); // initial value will be null
    ```

    **Using API:**

    ```jsx theme={null}
    const contactElement = useContactUtils();
    contactElement.getContactList().subscribe((response) => {
      console.log(response); // initial value will be null
    });
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const contactElement = Velt.getContactElement();
    contactElement.getContactList().subscribe((response) => {
      console.log(response); // initial value will be null
    });
    ```
  </Tab>
</Tabs>

#### onContactSelected

* This event is triggered when a contact is selected from the contact dropdown in the Comment Dialog.
* Use the event object to determine if the selected contact has access to the document using fields like `isOrganizationContact`, `isDocumentContact` and `documentAccessType`.
* If the selected contact doesn't have access to the document, you can show an invite dialog to the user to invite the contact to the document.

The returned data will be in the following schema:

```jsx theme={null}
export class UserContactSelectedPayload {
    contact!: UserContact; // Selected Contact.
    isOrganizationContact!: boolean; // Is user part of organization contact.
    isDocumentContact!: boolean; // Is user part of document contact.
    documentAccessType!: string; // Document access type.
}
```

<Tabs>
  <Tab title="React / Next.js">
    **Using Hooks:**

    ```jsx theme={null}
    const selectedContact = useContactSelected();

    useEffect(() => {
    console.log('selectedContact: ', selectedContact);
    }, [selectedContact]);

    ```

    **Using API:**

    ```jsx theme={null}
    const contactElement = client.getContactElement();

    contactElement.onContactSelected().subscribe((selectedContact: any) => {
      console.log('selectedContact : ', selectedContact);
    });
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const contactElement = Velt.getContactElement();

    contactElement.onContactSelected().subscribe((selectedContact: any) => {
    console.log('selectedContact: ', selectedContact);
    });

    ```
  </Tab>
</Tabs>

#### setAtHereLabel

* This allows you to modify the default text of the @here feature. eg: @all, @everyone, @team, etc.

<Tabs>
  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments atHereLabel='@all'>
    ```

    **Using Hooks:**

    ```jsx theme={null}
    const contactElement = useContactUtils();

    useEffect(() => {
      contactElement.setAtHereLabel("@all");
    }, [contactElement]);
    ```

    **Using API Method:**

    ```jsx theme={null}
    const contactElement = client.getContactElement();
    contactElement.setAtHereLabel("@all");
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using Props:**

    ```jsx theme={null}
    <velt-comments at-here-label="@all">
    ```

    **Using API Method:**

    ```jsx theme={null}
    const contactElement = Velt.getContactElement();
    contactElement.setAtHereLabel("@all");
    ```
  </Tab>
</Tabs>

#### setAtHereDescription

* Customize the description that appears for the @here mention.

<Tabs>
  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments atHereDescription="Notify all users in this document" />
    ```

    **Using Hooks:**

    ```jsx theme={null}
    const contactElement = useContactUtils();

    useEffect(() => {
      contactElement.setAtHereDescription("Notify all users in this document");
    }, [contactElement]);
    ```

    **Using API Method:**

    ```jsx theme={null}
    const contactElement = client.getContactElement();
    contactElement.setAtHereDescription("Notify all users in this document");
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using Props:**

    ```html theme={null}
    <velt-comments
      at-here-description="Notify all users in this document"
    ></velt-comments>
    ```

    **Using API Method:**

    ```javascript theme={null}
    const contactElement = Velt.getContactElement();
    contactElement.setAtHereDescription("Notify all users in this document");
    ```
  </Tab>
</Tabs>

#### showMentionGroupsFirst

* Show the user groups in the @mentions dropdown menu before the non-group users.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments showMentionGroupsFirst={true} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comments show-mention-groups-first="true"></velt-comments>
    ```
  </Tab>
</Tabs>

#### showMentionGroupsOnly

* Show only the user groups in the @mentions dropdown menu and not the non-group users.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments showMentionGroupsOnly={true} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comments show-mention-groups-only="true"></velt-comments>
    ```
  </Tab>
</Tabs>

#### subscribeCommentAnnotation

* Subscribes to a comment annotation
* Params: [SubscribeCommentAnnotationRequest](/api-reference/sdk/models/data-models#subscribecommentannotationrequest)
* Returns: [SubscribeCommentAnnotationEvent](/api-reference/sdk/models/data-models#subscribecommentannotationevent)

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const subscribeCommentAnnotationRequest = {
      annotationId: 'ANNOTATION_ID'
    };

    // Hook
    const { subscribeCommentAnnotation } = useSubscribeCommentAnnotation();
    const subscribeCommentAnnotationEvent = await subscribeCommentAnnotation(subscribeCommentAnnotationRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const subscribeCommentAnnotationEvent = await commentElement.subscribeCommentAnnotation(subscribeCommentAnnotationRequest);

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const subscribeCommentAnnotationRequest = {
      annotationId: 'ANNOTATION_ID'
    };

    const commentElement = Velt.getCommentElement();
    const subscribeCommentAnnotationEvent = await commentElement.subscribeCommentAnnotation(subscribeCommentAnnotationRequest);
    ```
  </Tab>
</Tabs>

#### unsubscribeCommentAnnotation

* Unsubscribes from a comment annotation
* Params: [UnsubscribeCommentAnnotationRequest](/api-reference/sdk/models/data-models#unsubscribecommentannotationrequest)
* Returns: [UnsubscribeCommentAnnotationEvent](/api-reference/sdk/models/data-models#unsubscribecommentannotationevent)

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const unsubscribeCommentAnnotationRequest = {
      annotationId: 'ANNOTATION_ID'
    };

    // Hook
    const { unsubscribeCommentAnnotation } = useUnsubscribeCommentAnnotation();
    const unsubscribeCommentAnnotationEvent = await unsubscribeCommentAnnotation(unsubscribeCommentAnnotationRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const unsubscribeCommentAnnotationEvent = await commentElement.unsubscribeCommentAnnotation(unsubscribeCommentAnnotationRequest);

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const unsubscribeCommentAnnotationRequest = {
      annotationId: 'ANNOTATION_ID'
    };

    const commentElement = Velt.getCommentElement();
    const unsubscribeCommentAnnotationEvent = await commentElement.unsubscribeCommentAnnotation(unsubscribeCommentAnnotationRequest);
    ```
  </Tab>
</Tabs>

#### updateContactList

* By default, the contact list is generated using the users in the organization and the document.
* However, if you do not want to use that feature or want to provide a custom list of contacts, you can use this method.
* By default, it will overwrite the current contact list. You can merge the provided contacts with the existing list by passing the merge flag as `{merge:true}`.
* When `filters: true` is passed, the sidebar People, Assigned, Tagged, and Involved filters are restricted to the custom contact list plus the current user.
* This method will only update the contact list in the current user session. It doesn't update the user contacts in the database or change the access control.

<Tabs>
  <Tab title="React / Next.js">
    **Using Hooks:**

    ```jsx theme={null}
    const contactElement = useContactUtils();

    useEffect(() => {
    contactElement.updateContactList([{userId: 'userId1', name: 'User Name', email: 'user1@velt.dev'}], {merge: false});
    }, [contactElement]);

    ```

    **Using API:**

    ```jsx theme={null}
    const contactElement = client.getContactElement();
    contactElement.updateContactList([{userId: 'userId1', name: 'User Name', email: 'user1@velt.dev'}], {merge: false});
    ```

    **Restrict sidebar filters to the contact list:**

    ```jsx theme={null}
    contactElement.updateContactList(contacts, { filters: true });
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const contactElement = Velt.getContactElement();
    contactElement.updateContactList([{userId: 'userId1', name: 'User Name', email: 'user1@velt.dev'}], {merge: false});
    ```

    **Restrict sidebar filters to the contact list:**

    ```jsx theme={null}
    contactElement.updateContactList(contacts, { filters: true });
    ```
  </Tab>
</Tabs>

#### updateContactListScopeForOrganizationUsers

* Sometimes you may want to show only certain types of contacts in the contact dropdown.
* By default, organization users will see all contacts in the organization, any user groups and any contacts added to the document.
* Using this method, you can restrict the contacts shown in the dropdown to only certain types.
* This only affects the Organization Users and not the Document Users. Document Users will always only see contacts added to the document.

Here are the available options:

* `all`: Show all the contacts
* `organization`: Show organization contacts.
* `organizationUserGroup`: Show organization user groups.
* `document`: Show document contacts.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const contactElement = client.getContactElement();
    contactElement.updateContactListScopeForOrganizationUsers(['all', 'organization', 'organizationUserGroup', 'document']);
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const contactElement = Velt.getContactElement();
    contactElement.updateContactListScopeForOrganizationUsers(['all', 'organization', 'organizationUserGroup', 'document']);
    ```
  </Tab>
</Tabs>

#### [setAnonymousUserDataProvider](/api-reference/sdk/api/api-methods#setanonymoususerdataprovider)

Register a provider to resolve email → `userId` mappings for users who are tagged by email in comments but are not part of the contact list. When a comment is saved and a tagged contact or `to` recipient has an email but no `userId`, the SDK calls the provider to look up the `userId` and backfills it into the comment data before persisting.

[Full implementation guide →](/self-host-data/users#anonymous-user-resolution)

#### autoCompleteScrollConfig

Customize virtual scroll behavior in autocomplete dropdown for @mentions.

Type: [`AutoCompleteScrollConfig`](/api-reference/sdk/models/data-models#autocompletescrollconfig)

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments
      autoCompleteScrollConfig={{
        itemSize: 28,
        minBufferPx: 100,
        maxBufferPx: 200,
        templateCacheSize: 20,
      }}
    />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comments
      autocomplete-scrollconfig='{
    "itemSize": 28,
    "minBufferPx": 100,
    "maxBufferPx": 200,
    "templateCacheSize": 20
    }'
    ></velt-comments>
    ```
  </Tab>
</Tabs>

# Metadata

#### addContext

Custom metadata allows you to add extra information to comments, enhancing their functionality. Here's what you can do with it:

* Render additional data on comments
* Position comment pins manually
* Create custom UI components
* Enable comment filtering on custom data

To add custom metadata, use one of the following events which has the `addContext` method. This method accepts an object with key-value pairs.

* `addCommentAnnotationDraft`
* `addCommentAnnotation`

Alternatively, you can pass `context` as a prop to most components that helps with creating new comment annotations. Eg:

* `VeltCommentTool`
* `VeltCommentComposer`
* `VeltCommentDialogComposer`
* `VeltInlineCommentsSection`

<img src="https://mintcdn.com/velt/gAz_vLsG-ukKamYM/images/addContext.png?fit=max&auto=format&n=gAz_vLsG-ukKamYM&q=85&s=7fcc3569ff4420fb7652f1124239cd89" alt="" width="1280" height="720" data-path="images/addContext.png" />

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Hook
    const commentEventCallbackData = useCommentEventCallback('addCommentAnnotation');
    useEffect(() => {
      if (commentEventCallbackData) {
        commentEventCallbackData.addContext({ customKey: 'customValue' });
      }
    }, [commentEventCallbackData]);

    // API Method
    const commentElement = client.getCommentElement();
    commentElement.on('addCommentAnnotation').subscribe((event) => {
    event.addContext({ customKey: 'customValue' });
    });

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.on('addCommentAnnotation').subscribe((event) => {
        event.addContext({ customKey: 'customValue' });
    });
    ```
  </Tab>
</Tabs>

#### updateContext

* Update the custom metadata associated with a comment annotation using the `updateContext` method.
* Utilize this method to update the context of a comment annotation at any time. For example, you might use this when the name of the dashboard containing the comment annotation changes.

The `commentElement.updateContext()` method accepts three parameters:

* The Comment Annotation ID
* The new metadata object
* An optional `updateContextConfig` object. Specify how the new metadata should be applied:
  * `{ merge: true }`: Merges the new metadata with the existing metadata
  * `{ merge: false }` or omitted: Replaces the existing metadata entirely (default behavior)

<Tabs>
  <Tab title="React / Next.js">
    Using API:

    ```js theme={null}
    const updatedContext = { customKey: "customValue" };
    const updateContextConfig = { merge: true };

    const commentElement = client.getCommentElement();
    commentElement.updateContext(
      COMMENT_ANNOTATION_ID,
      updatedContext,
      updateContextConfig,
    );
    ```
  </Tab>

  <Tab title="Other Frameworks">
    Using API method:

    ```js theme={null}
    const updatedContext = { customKey: "customValue" };
    const updateContextConfig = { merge: true };

    const commentElement = client.getCommentElement();
    commentElement.updateContext(
      COMMENT_ANNOTATION_ID,
      updatedContext,
      updateContextConfig,
    );
    ```
  </Tab>
</Tabs>

#### setContextProvider

Provide custom context (metadata) dynamically for comments using a provider function. This method allows you to return context based on the document and location where a comment is being added.
The SDK will call this function whenever a new comment annotation is created so you can provide dynamic values for the context.

The provider function receives `documentId` and optional `location` parameters and can return a [`CommentContext`](/api-reference/sdk/models/data-models#commentcontext) object, `null`, `undefined`, or a Promise resolving to any of these values.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Hook
    import { useCallback, useEffect } from 'react';
    import { useSetContextProvider } from '@veltdev/react';

    const contextProvider = useCallback((documentId, location) => {
    return {
    customKey: 'customValue'
    };
    }, []);

    const { setContextProvider } = useSetContextProvider();

    useEffect(() => {
    if (setContextProvider && contextProvider) {
    setContextProvider(contextProvider);
    }
    }, []);

    // API Method
    const commentElement = client.getCommentElement();
    commentElement.setContextProvider((documentId, location) => {
    return {
    customKey: 'customValue'
    };
    });

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.setContextProvider((documentId, location) => {
      return {
        customKey: 'customValue'
      };
    });
    ```
  </Tab>
</Tabs>

#### setContextInPageModeComposer

Set context data for the page mode composer programmatically.

Accepts a [`PageModeComposerConfig`](/api-reference/sdk/models/data-models#pagemodecomposerconfig) object. Pass custom context data that will be included when a comment is created through the page mode composer.

API Method: [`setContextInPageModeComposer()`](/api-reference/sdk/api/api-methods#setcontextinpagemodecomposer)

<Note>
  For automatic context passing when opening the comment sidebar via the comment
  tool, see [contextInPageModeComposer](#contextinpagemodecomposer).
</Note>

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Using Hook
    const commentElement = useCommentUtils();

    // Set context with optional target element
    commentElement.setContextInPageModeComposer({
    context: { documentId: 'doc-123', section: 'intro' },
    targetElementId: 'element-1'
    });

    // Using API Method
    const commentElement = client.getCommentElement();
    commentElement.setContextInPageModeComposer({
    context: { documentId: 'doc-123', section: 'intro' },
    targetElementId: 'element-1'
    });

    // Set only context without target element
    commentElement.setContextInPageModeComposer({
    context: { documentId: 'doc-123' }
    });

    // Clear the context and target element
    commentElement.setContextInPageModeComposer({
    context: null,
    targetElementId: null
    });

    // Preserve context after submission
    commentElement.setContextInPageModeComposer({
    context: { documentId: 'doc-123', section: 'intro' },
    targetElementId: 'element-1',
    clearContext: false
    });

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const commentElement = Velt.getCommentElement();

    // Set context with optional target element
    commentElement.setContextInPageModeComposer({
      context: { documentId: 'doc-123', section: 'intro' },
      targetElementId: 'element-1'
    });

    // Set only context without target element
    commentElement.setContextInPageModeComposer({
      context: { documentId: 'doc-123' }
    });

    // Clear the context and target element
    commentElement.setContextInPageModeComposer({
      context: null,
      targetElementId: null
    });

    // Preserve context after submission
    commentElement.setContextInPageModeComposer({
      context: { documentId: 'doc-123', section: 'intro' },
      targetElementId: 'element-1',
      clearContext: false
    });
    ```
  </Tab>
</Tabs>

#### clearPageModeComposerContext

Clear context data from page mode composer. This is useful when you are using sidebar in embed mode and have to clear the context from page mode composer manually.

API Method: [`clearPageModeComposerContext()`](/api-reference/sdk/api/api-methods#clearpagemodecomposercontext)

* Params: none
* Returns: `void`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.clearPageModeComposerContext();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <script>
      const commentElement = Velt.getCommentElement();
      commentElement.clearPageModeComposerContext();
    </script>
    ```
  </Tab>
</Tabs>

# Aggregation

### Overview

**Aggregation** lets you filter, group, and render comments that match specific criteria — without writing any custom logic.\
It's especially powerful when comments are tied to structured data such as products, categories, or financial entities.

You can group comments by:

* Metadata (`context`)
* Element IDs (`targetElementId`)
* Resource identifiers (`documentId`, `folderId`, `locationId`)

In short: aggregation helps you **query comments like data**.

***

### When to Use Aggregation

Use aggregation when your app involves complex relationships or taxonomy-based filtering.

#### 🧩 Tables & Dashboards

**Supply Chain Example**\
A product can belong to multiple categories. When viewing data by category, you may want to display all comments made on products within that category — or even across product variants.

**Financial Planning Example**\
A budget item (e.g., *Marketing Q1*) can have multiple subcategories (e.g., *Paid Ads*, *Sponsorships*).\
Aggregation allows you to show all comments related to a specific period, department, or account group — even if those comments live across different documents or views.

***

### How It Works

#### Comment Metadata Fields

Each comment can include one or more of the following identifiers or metadata fields:

| Field             | Description                                      |
| ----------------- | ------------------------------------------------ |
| `folderId`        | Target folder ID                                 |
| `documentId`      | Target document ID                               |
| `locationId`      | Target location ID                               |
| `targetElementId` | Target DOM element ID                            |
| `context`         | Custom metadata object for grouping or filtering |

***

#### Comment Creation

When you use any of the above identifiers or metadata fields in the following supported components, they automatically get **attached to the comment** at the time it's created.\
This ensures that each comment carries the correct folder, document, element, or context metadata — so it can later be filtered or grouped accurately.

**Supported Components**

* Inline Comments Section
* Comment Tool

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Comment Tool with context metadata
    <VeltCommentTool
      targetElementId="cell-jan-cheese-zurich"
      context={{
        month: "jan",
        year: "2024",
        product: "cheese",
        location: "zurich"
      }}
    />

    // Inline Comments Section with context

    <VeltInlineCommentsSection
      targetElementId="budget-item-marketing-q1"
      context={{
        department: "marketing",
        quarter: "Q1",
        category: "paid-ads"
      }}
    />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <!-- Comment Tool with context metadata -->
    <velt-comment-tool
      target-element-id="cell-jan-cheese-zurich"
      context='{
        "month": "jan",
        "year": "2024",
        "product": "cheese",
        "location": "zurich"
      }'
    >
    </velt-comment-tool>

    <!-- Inline Comments Section with context -->

    <velt-inline-comments-section
    target-element-id="budget-item-marketing-q1"
    context='{
    "department": "marketing",
    "quarter": "Q1",
    "category": "paid-ads"
    }'

    > </velt-inline-comments-section>

    ```
  </Tab>
</Tabs>

***

#### Comment Rendering

When the above identifiers or metadata fields are passed to the following rendering components, they determine **which comments are displayed**.
Only comments that match the provided folder, document, element, or context values will be rendered in that component.

**Supported Components**

* Comment Bubble
* Inline Comments Section
* Comment Pin (Standalone) — *does not support* `targetElementId`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Comment Bubble - filter by context
    <VeltCommentBubble
      context={{ product: "cheese" }}
      contextOptions={{ partialMatch: true }}
    />

    // Comment Bubble - filter by target element
    <VeltCommentBubble targetElementId="cell-jan-cheese-zurich" />

    // Inline Comments Section - filter by context
    <VeltInlineCommentsSection
      context={{ department: "marketing" }}
      contextOptions={{ partialMatch: true }}
    />

    // Comment Pin - filter by context (no targetElementId support)
    <VeltCommentPin
      context={{ product: "cheese", month: "jan" }}
    />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <!-- Comment Bubble - filter by context -->
    <velt-comment-bubble
      context='{ "product": "cheese" }'
      context-options='{ "partialMatch": true }'
    >
    </velt-comment-bubble>

    <!-- Comment Bubble - filter by target element -->

    <velt-comment-bubble target-element-id="cell-jan-cheese-zurich"></velt-comment-bubble>

    <!-- Inline Comments Section - filter by context -->

    <velt-inline-comments-section
    context='{ "department": "marketing" }'
    context-options='{ "partialMatch": true }'

    > </velt-inline-comments-section>

    <!-- Comment Pin - filter by context (no targetElementId support) -->

    <velt-comment-pin
    context='{ "product": "cheese", "month": "jan" }'

    > </velt-comment-pin>

    ```
  </Tab>
</Tabs>

***

### Filtering Behavior

When filtering comments, only annotations matching **all provided fields** will be shown:

```

folderId
documentId
locationId
targetElementId
context

```

***

### `Context` Matching

You can choose between two matching modes for the `context` field: **Full Match** (default) or **Partial Match**.

***

#### 🔒 Full Match (Default)

A comment matches **only if all fields** in its context exactly match your filter criteria.

**Example:**

```js theme={null}
// Comment context
{ month: "jan", product: "cheese", location: "zurich" }

// Filters
{ month: "jan", product: "cheese", location: "zurich" }  ✅ Matches
{ month: "jan", product: "cheese" }                      ❌ No match (missing field)
{ month: "jan", product: "cheese", year: "2024" }        ❌ No match (extra field)
```

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Full match (default)
    <VeltCommentBubble
      context={{ month: "jan", product: "cheese", location: "zurich" }}
    />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <!-- Full match (default) -->
    <velt-comment-bubble
      context='{ "month": "jan", "product": "cheese", "location": "zurich" }'
    >
    </velt-comment-bubble>
    ```
  </Tab>
</Tabs>

***

#### 🔍 Partial Match

Enable partial matching with `contextOptions={{ partialMatch: true }}`.

A comment matches if **all fields in your filter exist in the comment's context**.\
Extra fields in the comment context don't prevent a match.

**Example:**

```js theme={null}
// Comment context
{ day: "01", week: "01", month: "jan", product: "cheese", location: "zurich" }

// Filters
{ product: "cheese" }                   ✅ Matches
{ day: "01", product: "cheese" }        ✅ Matches
{ product: "cheese", category: "dairy"} ❌ No match (missing field)
```

**Example**

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    {/* Comment Bubble with Partial Match */}
    <VeltCommentBubble
      context={{ product: "cheese" }}
      contextOptions={{ partialMatch: true }}
    />

    {/* Comment Tool with Partial Match */}

    <VeltCommentTool
      targetElementId="element_id"
      context={{ product: "cheese" }}
      contextOptions={{ partialMatch: true }}
    />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <!-- Comment Bubble with Partial Match -->
    <velt-comment-bubble
      context='{ "product": "cheese" }'
      context-options='{ "partialMatch": true }'
    >
    </velt-comment-bubble>

    <!-- Comment Tool with Partial Match -->

    <velt-comment-tool
    target-element-id="element_id"
    context='{ "product": "cheese" }'
    context-options='{ "partialMatch": true }'

    > </velt-comment-tool>

    ```
  </Tab>
</Tabs>

***

### Grouping Matched Comment Annotations

When multiple comments match your filter criteria, you can **group them** into a single visual element — such as a Comment Bubble, Comment Pin, or Inline Comments Section — for a cleaner, multi-threaded UI.

**How it works:**

* Enable grouping globally with `groupMatchedComments`
* All matching annotations are shown as one grouped thread
* The comment count shows total grouped annotations
* Users can expand to view and interact with all related threads

**Example**

If there are three comments for `"product: cheese"` across different months, they can all appear in one Comment Bubble when you filter by `{ product: "cheese" }`.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Enable grouping globally
    <VeltComments groupMatchedComments={true} />

    // Grouped Comment Bubble
    <VeltCommentBubble
      context={{ product: "cheese" }}
      contextOptions={{ partialMatch: true }}
    />

    // Enable/disable via API
    const commentElement = client.getCommentElement();
    commentElement.enableGroupMatchedComments();
    commentElement.disableGroupMatchedComments();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <!-- Enable grouping globally -->
    <velt-comments group-matched-comments="true"></velt-comments>

    <!-- Grouped Comment Bubble -->

    <velt-comment-bubble
    context='{ "product": "cheese" }'
    context-options='{ "partialMatch": true }'
    comment-count-type="total"

    > </velt-comment-bubble>

    <script>
      const commentElement = Velt.getCommentElement();
      commentElement.enableGroupMatchedComments();
      commentElement.disableGroupMatchedComments();
    </script>

    ```
  </Tab>
</Tabs>

***

# Private Comments

<Info>
  The visibility system uses two separate sets of values:

  * **API methods** (on this page) use [`CommentVisibilityConfig`](/api-reference/sdk/models/data-models#commentvisibilityconfig) with 3 values: `'public'`, `'organizationPrivate'`, `'restricted'`.
  * **UI wireframes** use the [`CommentVisibilityOption`](/api-reference/sdk/models/data-models#commentvisibilityoption) enum with 4 values: `'restrictedSelf'`, `'restrictedSelectedPeople'`, `'organizationPrivate'`, `'public'`.

  The API's single `'restricted'` value covers both "self-only" and "selected people" — distinguished by whether `userIds` is provided.
</Info>

To use this feature, you need to first **enable** it in [Velt Console](https://console.velt.dev/dashboard/config/appconfig).

#### [updateVisibility](/api-reference/sdk/api/api-methods#updatevisibility)

Manage who can view a comment annotation by updating its visibility settings. Use this method to control whether a comment is public, restricted to your organization, or visible only to specific users. The resulting setting is stored on the annotation as [`visibilityConfig`](/api-reference/sdk/models/data-models#commentannotationvisibilityconfig).

* To use this feature, you need to first enable it in [Velt Console](https://console.velt.dev/dashboard/config/appconfig)
* Params: [CommentVisibilityConfig](/api-reference/sdk/models/data-models#commentvisibilityconfig)
  * `type`:
    * `'public'`: Comment visible to all users
    * `'organizationPrivate'`: Comment visible only to users in the specified organization. Even if someone is added to the document but not to the organization, they will not be able to view the comment.
    * `'restricted'`: Comment visible only to the specified users; the current user is always included
  * `organizationId`: string; required if `type` is `organizationPrivate`
  * `userIds`: string\[]; optional when `type` is `'restricted'` — current user is always appended
* Returns: `void`

<Note>When `type` is `'restricted'`, the SDK automatically appends the current user's `userId` to `userIds` if it is not already present. This applies whether `userIds` is empty or contains an explicit list that excludes the author.</Note>

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();

    // Set comment to be visible only to the organization
    commentElement.updateVisibility({
      annotationId: "annotationId",
      type: 'organizationPrivate',
      organizationId: 'org-123'
    });

    // Set comment to be private (current user always included in restricted access)
    commentElement.updateVisibility({
      annotationId: "annotationId",
      type: 'restricted'
    });

    // Set comment to be private (visible only to specific users)
    commentElement.updateVisibility({
      annotationId: "annotationId",
      type: 'restricted',
      userIds: ['user-1', 'user-2']
    });

    // Set comment to be public
    commentElement.updateVisibility({
      annotationId: "annotationId",
      type: 'public'
    });
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const commentElement = Velt.getCommentElement();

    // Set comment to be visible only to the organization
    commentElement.updateVisibility({
    annotationId: "annotationId",
    type: 'organizationPrivate',
    organizationId: 'org-123'
    });

    // Set comment to be private (current user always included in restricted access)
    commentElement.updateVisibility({
    annotationId: "annotationId",
    type: 'restricted'
    });

    // Set comment to be private (visible only to specific users)
    commentElement.updateVisibility({
    annotationId: "annotationId",
    type: 'restricted',
    userIds: ['user-1', 'user-2']
    });

    // Set comment to be public
    commentElement.updateVisibility({
    annotationId: "annotationId",
    type: 'public'
    });

    ```
  </Tab>
</Tabs>

#### [enablePrivateMode](/api-reference/sdk/api/api-methods#enableprivatemode)

Set the default visibility for all new comments created by the current user.

* Params: [PrivateModeConfig](/api-reference/sdk/models/data-models#privatemodeconfig)
  * `type`:
    * `'restricted'`: New comments visible only to the specified users; the current user is always included
    * `'organizationPrivate'`: New comments visible only to users in the current organization
  * `userIds`: string\[]; optional when `type` is `'restricted'` — current user is always appended
* Returns: `void`

<Note>When `type` is `'restricted'`, the SDK automatically appends the current user's `userId` to `userIds` if it is not already present. This applies whether `userIds` is empty or contains an explicit list that excludes the author.</Note>

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    // Restrict all new comments to specific users
    commentElement.enablePrivateMode({ type: 'restricted', userIds: ['user-1', 'user-2'] });
    // Restrict all new comments to the current organization
    commentElement.enablePrivateMode({ type: 'organizationPrivate' });
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const commentElement = Velt.getCommentElement();
    // Restrict all new comments to specific users
    commentElement.enablePrivateMode({ type: 'restricted', userIds: ['user-1', 'user-2'] });
    // Restrict all new comments to the current organization
    commentElement.enablePrivateMode({ type: 'organizationPrivate' });
    ```
  </Tab>
</Tabs>

#### [disablePrivateMode](/api-reference/sdk/api/api-methods#disableprivatemode)

Revert new comment visibility to default public visibility.

* Returns: `void`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    // Revert to default public visibility
    commentElement.disablePrivateMode();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const commentElement = Velt.getCommentElement();
    // Revert to default public visibility
    commentElement.disablePrivateMode();
    ```
  </Tab>
</Tabs>

#### visibilityOptions

Show a visibility banner on the comment composer that lets users set a comment's visibility to `public`, `organization-private`, `restricted-self`, or `restricted` before submitting. Users can also change visibility after submission from the thread options menu.

Default: `false`

<Tabs>
  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments visibilityOptions={true} />
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableVisibilityOptions();
    commentElement.disableVisibilityOptions();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using Props:**

    ```html theme={null}
    <velt-comments visibility-options="true"></velt-comments>
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableVisibilityOptions();
    commentElement.disableVisibilityOptions();
    ```
  </Tab>
</Tabs>

#### visibilityOptionClicked

Subscribe to this event to be notified when a user selects a visibility option. Emits a [`VisibilityOptionClickedEvent`](/api-reference/sdk/models/data-models#visibilityoptionclickedevent).

#### Setting visibility at comment creation time

If you are creating comments using API, then pass a [`CommentVisibilityConfig`](/api-reference/sdk/models/data-models#commentvisibilityconfig) as the optional `visibility` field on [`AddCommentRequest`](/api-reference/sdk/models/data-models#addcommentrequest) to pre-set visibility when programmatically adding a comment.

<Tabs>
  <Tab title="React / Next.js">
    **Using Hooks:**

    ```jsx theme={null}
    const addCommentRequest = {
      annotationId: 'ANNOTATION_ID',
      comment: {
        commentText: 'This is a comment',
        commentHtml: '<p>This is a comment</p>',
      },
      visibility: {
        type: 'restricted',
        userIds: ['user-1', 'user-2']
      }
    };

    const { addComment } = useAddComment();
    const addCommentEventData = await addComment(addCommentRequest);

    ```

    **Using API:**

    ```jsx theme={null}
    const addCommentRequest = {
      annotationId: 'ANNOTATION_ID',
      comment: {
        commentText: 'This is a comment',
        commentHtml: '<p>This is a comment</p>',
      },
      visibility: {
        type: 'restricted',
        userIds: ['user-1', 'user-2']
      }
    };

    const commentElement = client.getCommentElement();
    const addCommentEventData = await commentElement.addComment(addCommentRequest);
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const addCommentRequest = {
      annotationId: 'ANNOTATION_ID',
      comment: {
        commentText: 'This is a comment',
        commentHtml: '<p>This is a comment</p>',
      },
      visibility: {
        type: 'restricted',
        userIds: ['user-1', 'user-2']
      }
    };

    const commentElement = Velt.getCommentElement();
    const addCommentEventData = await commentElement.addComment(addCommentRequest);

    ```
  </Tab>
</Tabs>

# Custom Lists

#### createCustomListDataOnAnnotation

* Add a custom dropdown list at the Comment Annotation level.
* Use this to add custom tags or categories to the comment.

<img src="https://mintcdn.com/velt/2O8vk8YlVD4Kq-ni/images/customization/comment-annotation-custom-list.png?fit=max&auto=format&n=2O8vk8YlVD4Kq-ni&q=85&s=49e69684842120873f9f58d5874f42d2" alt="" width="2560" height="1440" data-path="images/customization/comment-annotation-custom-list.png" />

```jsx theme={null}
let customList = [
    { id: 'violent', label: 'Violent' },
    { id: 'inappropriate', label: 'Inappropriate' },
    { id: 'robbery', label: 'Robbery' },
    { id: 'nsfw', label: 'NSFW' },
];

const customListDataOnCommentAnnotation = {
	  type: 'multi', // choose from 'multi' or 'single'
    placeholder: 'Select a category',
    data: customList, // your customList data here
};
```

<Tabs>
  <Tab title="React / Next.js with hooks">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments customListDataOnAnnotation={customListDataOnCommentAnnotation} />
    ```

    **API Method:**

    ```jsx theme={null}
    const commentElement = useCommentUtils();
    commentElement.createCustomListDataOnAnnotation(
      customListDataOnCommentAnnotation,
    );
    ```
  </Tab>

  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments customListDataOnAnnotation={customListDataOnCommentAnnotation} />
    ```

    **API Method:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.createCustomListDataOnAnnotation(
      customListDataOnCommentAnnotation,
    );
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();			
    commentElement.createCustomListDataOnAnnotation(customListDataOnCommentAnnotation);
    ```
  </Tab>
</Tabs>

#### createCustomListDataOnComment

You can have custom dropdown lists appear when certain `hotkeys` are pressed.

When you press a hotkey inside the Comment Dialog composer, it will open a dropdown list of items that you can select.

<img src="https://mintcdn.com/velt/y_bUi9B-cnWLxN8L/images/customization/custom-list-1.png?fit=max&auto=format&n=y_bUi9B-cnWLxN8L&q=85&s=6f03afec1c52499cf210ef46c44af51b" alt="" width="1280" height="720" data-path="images/customization/custom-list-1.png" />

Selecting an item frop the dropdown list will add a chip that inside the comment text.

<img src="https://mintcdn.com/velt/y_bUi9B-cnWLxN8L/images/customization/custom-list-2.png?fit=max&auto=format&n=y_bUi9B-cnWLxN8L&q=85&s=4c8b1d876bb748347bae48707fdf3b3d" alt="" width="1280" height="720" data-path="images/customization/custom-list-2.png" />

<Tip>
  Grouped lists: Useful for workflows like issue trackers (e.g., group by
  "Priority" or "Status"), allowing users to quickly refer and insert custom
  entities from your app. With this feature, you can combine multiple entity
  types into one drop down just like Linear.
</Tip>

<Warning>
  Make sure the hotkey is a single character such as `#` or `/`.
</Warning>

The items in the list must be in the following schema:

<Note>
  Use `AutocompleteGroup` only for grouped lists. For flat lists, do not include
  `groups` on the config object or `groupId` on items.
</Note>

```jsx theme={null}
export class AutocompleteGroup {
    id!: string;
    name!: string;
}

export class AutocompleteItem {
    id!: string; // Unique identifier
    name!: string; // Item name. This appears as the main item text in the UI.
    description?: string; // Item description. This appears as the secondary item text in the UI.
    icon?: { url?: string; svg?: string }; // Item icon. Either URL or inline SVG.
    link?: string; // Item link. You can use this to open a link when the item is clicked. Check the event listener below for more details.
    groupId?: string; // Optional: assigns item to a group (by AutocompleteGroup.id)
}
```

##### **Flat List Implementation**

```jsx theme={null}
let customList = [
  {
    id: "1",
    name: "File 1",
    description: "File Description 1",
    icon: { url: "https://cdn-icons-png.flaticon.com/512/9496/9496432.png" },
  },
  {
    id: "2",
    name: "File 2",
    description: "File Description 2",
    icon: { url: "https://cdn-icons-png.flaticon.com/512/11471/11471469.png" },
  },
  {
    id: "3",
    name: "File 3",
    description: "File Description 3",
    icon: { url: "https://cdn-icons-png.flaticon.com/512/2656/2656402.png" },
  },
];

const customListDataOnComment = {
  hotkey: "UNIQUE_HOTKEY", // only single charater is allowed. eg: '#'
  type: "custom",
  data: customList, // your customList data here
};
```

<Tabs>
  <Tab title="React / Next.js with Hooks">
    ```jsx theme={null}
    // Using Props
    <VeltComments customListDataOnComment={customListDataOnComment} />

    // Hook
    const commentElement = useCommentUtils();
    commentElement.createCustomListDataOnComment(customListDataOnComment);

    ```
  </Tab>

  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Using Props
    <VeltComments customListDataOnComment={customListDataOnComment} />

    // Hook
    const commentElement = client.getCommentElement();
    commentElement.createCustomListDataOnComment(customListDataOnComment);
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.createCustomListDataOnComment(customListDataOnComment);
    ```
  </Tab>
</Tabs>

##### **Grouped List Implementation**

```ts theme={null}
const customListWithGroups = {
  hotkey: "$",
  type: "custom",
  groups: [
    { id: "categories", name: "Categories" },
    { id: "priorities", name: "Priorities" },
  ],
  data: [
    // Categories group
    {
      id: "bug_1",
      name: "Bug 1",
      description: "Bug report 1",
      groupId: "categories",
      icon: { svg: "<svg></svg>" },
    },
    {
      id: "feature_2",
      name: "Feature Request 2",
      description: "New feature 2",
      groupId: "categories",
      icon: { url: "https://random.png" },
    },
    // Priorities group
    {
      id: "high_1",
      name: "High Priority 1",
      description: "Urgent task 1",
      groupId: "priorities",
      icon: { url: "https://random.png" },
    },
    {
      id: "medium_2",
      name: "Medium Priority 2",
      description: "Normal task 2",
      groupId: "priorities",
      icon: { svg: "<svg></svg>" },
    },
    // Ungrouped items
    {
      id: "misc_1",
      name: "Miscellaneous 1",
      description: "Other items 1",
      icon: { url: "https://random.png" },
    },
    {
      id: "note_2",
      name: "Note 2",
      description: "General note 2",
      icon: { svg: "<svg></svg>" },
    },
  ],
};
```

<Tabs>
  <Tab title="React / Next.js with Hooks">
    ```ts theme={null}
    // Using Props
    <VeltComments customListDataOnComment={customListWithGroups} />

    // Hook
    const commentElement = useCommentUtils();
    commentElement.createCustomListDataOnComment(customListWithGroups);

    ```
  </Tab>

  <Tab title="React / Next.js">
    ```ts theme={null}
    const commentElement = client.getCommentElement();
    commentElement.createCustomListDataOnComment(customListWithGroups);
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.createCustomListDataOnComment(customListWithGroups);
    ```
  </Tab>
</Tabs>

##### **Listen to click events on chips**

After the comment is saved, the item will be rendered as a chip on the comment content. When the user clicks on it, you will get an event callback with the data of the clicked chip (`AutocompleteItem`).

<Info>
  This event will also be triggered when the user clicks on the contact chips
  added via the @mentions feature.
</Info>

<Tabs>
  <Tab title="React / Next.js with Hooks">
    ```jsx theme={null}
    let autocompleteChipData = useAutocompleteChipClick(); 
    ```
  </Tab>

  <Tab title="React / Next.js">
    ```jsx theme={null}
    const autocompleteElement = client.getAutocompleteElement();
    const subscription = autocompleteElement.onAutocompleteChipClick().subscribe((_data) => {
      console.log(_data);
    });
    ```

    To unsubscribe from the subscription:

    ```jsx theme={null}
    subscription?.unsubscribe()
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const autocompleteElement = Velt.getAutocompleteElement();
    const subscription = autocompleteElement.onAutocompleteChipClick().subscribe((_data) => {
      console.log(_data);
    });
    ```

    To unsubscribe from the subscription:

    ```jsx theme={null}
    subscription?.unsubscribe()
    ```
  </Tab>
</Tabs>

#### customAutocompleteSearch

* Handle autocomplete search for custom list. You should use this if you have a large list that you want to plug into the autocomplete dropdown, and search directly your own data source.
* Event: [`AutocompleteSearchEvent`](/api-reference/sdk/models/data-models#autocompletesearchevent)

<Tabs>
  <Tab title="React / Next.js">
    <Steps>
      <Step title="Enable the feature">
        ```jsx theme={null}
        // Enable via props
        <VeltComments customAutocompleteSearch={true} />

        // Or, enable via Comment Element API
        const commentElement = client.getCommentElement();
        commentElement.enableCustomAutocompleteSearch();
        commentElement.disableCustomAutocompleteSearch();

        ```
      </Step>

      <Step title="Set initial list">
        ```jsx theme={null}
        // For @mentions feature
        contactElement.updateContactList(users);

        // For custom list feature
        commentElement.createCustomListDataOnComment({
            hotkey: "#",
            type: "custom",
            data: customListData,
        });
        ```
      </Step>

      <Step title="Handle search event">
        ```jsx theme={null}
        commentElement.on('autocompleteSearch').subscribe(async (inputData) => {
            const searchText = inputData.searchText;

            // For @mentions feature
            if (inputData.type === 'contact') {
                const filteredUsersData = await __your_api_call__(searchText);
                contactElement.updateContactList(filteredUsersData, { merge: false });
            }

            // For custom list feature
            if (inputData.type === 'custom') {
                const filteredListData = await __your_api_call__(searchText, autocompleteData);
                commentElement.createCustomListDataOnComment({
                    hotkey: "#",
                    type: "custom",
                    data: filteredListData,
                });
            }

        });

        ```
      </Step>
    </Steps>
  </Tab>

  <Tab title="Other Frameworks">
    <Steps>
      <Step title="Enable the feature">
        ```js theme={null}
        // Enable via attribute
        <velt-comments custom-autocomplete-search="true"></velt-comments>

        // Or, enable via Comment Element API
        const commentElement = Velt.getCommentElement();
        commentElement.enableCustomAutocompleteSearch();
        commentElement.disableCustomAutocompleteSearch();
        ```
      </Step>

      <Step title="Set initial list">
        ```js theme={null}
        commentElement.createCustomListDataOnComment({
            hotkey: "#",
            type: "custom",
            data: customListData,
        });
        ```
      </Step>

      <Step title="Handle search event">
        ```js theme={null}
        commentElement.on('autocompleteSearch').subscribe(async (inputData) => {
            const searchText = inputData.searchText;

            if (inputData.type === 'custom') {
                const filteredListData = await __your_api_call__(searchText, autocompleteData);
                commentElement.createCustomListDataOnComment({
                    hotkey: "#",
                    type: "custom",
                    data: filteredListData,
                });
            }

        });

        ```
      </Step>
    </Steps>
  </Tab>
</Tabs>

# Event Subscription

### [on](/api-reference/sdk/api/api-methods#on)

Subscribe to Comment Events. Here is the list of events you can subscribe to and the event objects you will receive.

| Category          | Event Type                     | Description                                                                                                       | Event Object                                                                                                 |
| ----------------- | ------------------------------ | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| Threads           | `addCommentAnnotationDraft`    | Triggered before `addCommentAnnotation` event clicks on the comment tool and the composer is rendered.            | [AddCommentAnnotationDraftEvent](/api-reference/sdk/models/data-models#addcommentannotationdraftevent)       |
| Threads           | `addCommentAnnotation`         | Add a new comment annotation                                                                                      | [AddCommentAnnotationEvent](/api-reference/sdk/models/data-models#addcommentannotationevent)                 |
| Threads           | `deleteCommentAnnotation`      | Delete a comment annotation                                                                                       | [DeleteCommentAnnotationEvent](/api-reference/sdk/models/data-models#deletecommentannotationevent)           |
| Messages          | `addComment`                   | Add a new comment                                                                                                 | [AddCommentEvent](/api-reference/sdk/models/data-models#addcommentevent)                                     |
| Messages          | `updateComment`                | Update an existing comment                                                                                        | [UpdateCommentEvent](/api-reference/sdk/models/data-models#updatecommentevent)                               |
| Messages          | `deleteComment`                | Delete a comment                                                                                                  | [DeleteCommentEvent](/api-reference/sdk/models/data-models#deletecommentevent)                               |
| @Mentions         | `assignUser`                   | Assign a user to a comment                                                                                        | [AssignUserEvent](/api-reference/sdk/models/data-models#assignuserevent)                                     |
| @Mentions         | `subscribeCommentAnnotation`   | Subscribe to a comment annotation                                                                                 | [SubscribeCommentAnnotationEvent](/api-reference/sdk/models/data-models#subscribecommentannotationevent)     |
| @Mentions         | `unsubscribeCommentAnnotation` | Unsubscribe from a comment annotation                                                                             | [UnsubscribeCommentAnnotationEvent](/api-reference/sdk/models/data-models#unsubscribecommentannotationevent) |
| @Mentions         | `autocompleteSearch`           | When user starts searching for a contact in the @mentions dropdown or for a list item in the custom list dropdown | [AutocompleteSearchEvent](/api-reference/sdk/models/data-models#autocompletesearchevent)                     |
| Attachments       | `addAttachment`                | Add an attachment to a comment                                                                                    | [AddAttachmentEvent](/api-reference/sdk/models/data-models#addattachmentevent)                               |
| Attachments       | `deleteAttachment`             | Delete an attachment from a comment                                                                               | [DeleteAttachmentEvent](/api-reference/sdk/models/data-models#deleteattachmentevent)                         |
| Attachments       | `attachmentDownloadClicked`    | Triggered when attachment download button is clicked                                                              | [AttachmentDownloadClickedEvent](/api-reference/sdk/models/data-models#attachmentdownloadclickedevent)       |
| Reactions         | `addReaction`                  | Add a reaction to a comment                                                                                       | [AddReactionEvent](/api-reference/sdk/models/data-models#addreactionevent)                                   |
| Reactions         | `deleteReaction`               | Delete a reaction from a comment                                                                                  | [DeleteReactionEvent](/api-reference/sdk/models/data-models#deletereactionevent)                             |
| Reactions         | `toggleReaction`               | Toggle a reaction on a comment                                                                                    | [ToggleReactionEvent](/api-reference/sdk/models/data-models#togglereactionevent)                             |
| Status & Priority | `updateStatus`                 | Update the status of a comment                                                                                    | [UpdateStatusEvent](/api-reference/sdk/models/data-models#updatestatusevent)                                 |
| Status & Priority | `resolveComment`               | Resolve a comment                                                                                                 | [ResolveCommentEvent](/api-reference/sdk/models/data-models#resolvecommentevent)                             |
| Status & Priority | `updatePriority`               | Update the priority of a comment                                                                                  | [UpdatePriorityEvent](/api-reference/sdk/models/data-models#updatepriorityevent)                             |
| Status & Priority | `approveCommentAnnotation`     | Approve a comment annotation                                                                                      | [ApproveCommentAnnotationEvent](/api-reference/sdk/models/data-models#approvecommentannotationevent)         |
| Status & Priority | `acceptCommentAnnotation`      | Accept a comment annotation                                                                                       | [AcceptCommentAnnotationEvent](/api-reference/sdk/models/data-models#acceptcommentannotationevent)           |
| Status & Priority | `rejectCommentAnnotation`      | Reject a comment annotation                                                                                       | [RejectCommentAnnotationEvent](/api-reference/sdk/models/data-models#rejectcommentannotationevent)           |
| Recordings        | `deleteRecording`              | Delete a recording from a comment                                                                                 | [DeleteRecordingEvent](/api-reference/sdk/models/data-models#deleterecordingevent)                           |
| Deep Links        | `copyLink`                     | Copy a deep link to a comment                                                                                     | [CopyLinkEvent](/api-reference/sdk/models/data-models#copylinkevent)                                         |
| Comment Sidebar   | `commentSidebarDataInit`       | Triggered when comment sidebar data is first loaded                                                               | [CommentSidebarDataInitEvent](/api-reference/sdk/models/data-models#commentsidebardatainitevent)             |
| Comment Sidebar   | `commentSidebarDataUpdate`     | Triggered when comment sidebar data is updated                                                                    | [CommentSidebarDataUpdateEvent](/api-reference/sdk/models/data-models#commentsidebardataupdateevent)         |
| UI                | `composerClicked`              | Triggered when comment composer is clicked                                                                        | [ComposerClickedEvent](/api-reference/sdk/models/data-models#composerclickedevent)                           |
| UI                | `composerTextChange`           | Triggered when text changes in any comment composer. Includes full draft annotation object and composer ID.       | [ComposerTextChangeEvent](/api-reference/sdk/models/data-models#composertextchangeevent)                     |
| UI                | `commentPinClicked`            | Triggered when a comment pin is clicked                                                                           | [CommentPinClickedEvent](/api-reference/sdk/models/data-models#commentpinclickedevent)                       |
| UI                | `commentBubbleClicked`         | Triggered when a comment bubble is clicked                                                                        | [CommentBubbleClickedEvent](/api-reference/sdk/models/data-models#commentbubbleclickedevent)                 |
| UI                | `linkClicked`                  | Triggered when a clickable link in comment content is clicked                                                     | [LinkClickedEvent](/api-reference/sdk/models/data-models#linkclickedevent)                                   |
| UI                | `commentToolClicked`           | Past-tense alias for `commentToolClick`, identical payload                                                        | [CommentToolClickedEvent](/api-reference/sdk/models/data-models#commenttoolclickedevent)                     |
| UI                | `sidebarButtonClicked`         | Past-tense alias for `sidebarButtonClick`, identical payload                                                      | [SidebarButtonClickedEvent](/api-reference/sdk/models/data-models#sidebarbuttonclickedevent)                 |
| Recorder          | `transcriptionDone`            | Triggered when a transcription is generated and ready                                                             | [TranscriptionDoneEvent](/api-reference/sdk/models/data-models#transcriptiondoneevent)                       |
| Threads           | `commentSaved`                 | Triggered when a comment annotation is saved to the database                                                      | [CommentSavedEvent](/api-reference/sdk/models/data-models#commentsavedevent)                                 |
| Threads           | `commentSaveTriggered`         | Triggered immediately when the save button is clicked, before async save completes                                | [CommentSaveTriggeredEvent](/api-reference/sdk/models/data-models#commentsavetriggeredevent)                 |
| Visibility        | `visibilityOptionClicked`      | Triggered when a user selects a visibility option                                                                 | [VisibilityOptionClickedEvent](/api-reference/sdk/models/data-models#visibilityoptionclickedevent)           |

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Hook
    const commentEventCallbackData = useCommentEventCallback('addCommentAnnotation');
    useEffect(() => {
      if (commentEventCallbackData) {
        // Handle comment action callback event response
      }
    }, [commentEventCallbackData]);

    // API Method
    const commentElement = client.getCommentElement();
    commentElement.on('addCommentAnnotation').subscribe((event) => {
        // Handle the event response
    });

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.on('addCommentAnnotation').subscribe((event) => {
        // Handle the event response
    });
    ```
  </Tab>
</Tabs>

# Attachments

#### enableAttachments

<img src="https://mintcdn.com/velt/kAkMSIYF4ZlrlwLm/images/file-attachment.png?fit=max&auto=format&n=kAkMSIYF4ZlrlwLm&q=85&s=00c2e3bb6c8c5929a950b9d49edb5305" alt="" width="1280" height="720" data-path="images/file-attachment.png" />

Whether file attachments are enabled.

Default: `true`

When this is on, users can attach image files to their comments. Users can download or delete an attachment. Users can attach multiple files at once.

Currently we support `.png`, `.jpg`, `.gif` (static & animated), `.svg` file types up to 15MB per file.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments attachments={true} />
    ```

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableAttachments();
    commentElement.disableAttachments();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comments attachments="true"></velt-comments>
    ```

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableAttachments();
    commentElement.disableAttachments();
    ```
  </Tab>
</Tabs>

#### enableAttachmentDownload

Controls whether clicking an attachment triggers a file download.

Default: `true`

When disabled, users can still click attachments but no download is triggered. The `attachmentDownloadClicked` event fires on every attachment click regardless of this setting.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Using Component Props
    <VeltComments attachmentDownload={true} />
    ```

    ```jsx theme={null}
    // Using API methods
    const commentElement = client.getCommentElement();
    commentElement.enableAttachmentDownload();
    commentElement.disableAttachmentDownload();
    ```

    ```jsx theme={null}
    // Listening to the event
    const commentEventCallbackData = useCommentEventCallback('attachmentDownloadClicked');
    useEffect(() => {
      if (commentEventCallbackData) {
        // Handle attachment download clicked event
      }
    }, [commentEventCallbackData]);
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <!-- Using HTML attributes -->
    <velt-comments attachment-download="true"></velt-comments>
    ```

    ```js theme={null}
    // Using API methods
    const commentElement = Velt.getCommentElement();
    commentElement.enableAttachmentDownload();
    commentElement.disableAttachmentDownload();
    ```

    ```js theme={null}
    // Listening to the event
    const commentElement = Velt.getCommentElement();
    commentElement.on('attachmentDownloadClicked').subscribe((event) => {
      // Handle attachment download clicked event
    });
    ```
  </Tab>
</Tabs>

#### enableScreenshot

Whether screenshot option is enabled in comments.

Default: `false`

When enabled, users can attach screenshots when adding comments. This provides a quick way to capture and share visual context.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Using Component Props
    <VeltComments screenshot={true} />

    // Using API methods
    const commentElement = client.getCommentElement();
    commentElement.enableScreenshot();
    commentElement.disableScreenshot();

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <!-- Using HTML attributes -->
    <velt-comments screenshot="true"></velt-comments>

    <script>
    // Using API methods
    const commentElement = Velt.getCommentElement();
    commentElement.enableScreenshot();
    commentElement.disableScreenshot();
    </script>
    ```
  </Tab>
</Tabs>

#### addAttachment

* Add an attachment to a specific comment annotation
* Params: [AddAttachmentRequest](/api-reference/sdk/models/data-models#addattachmentrequest)
* Returns: Promise\<[AddAttachmentResponse\[\]](/api-reference/sdk/models/data-models#addattachmentresponse)>

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const addAttachmentRequest = {
      annotationId: 'ANNOTATION_ID',
      files: '<Files[]>'
    };

    // Hook
    const { addAttachment } = useAddAttachment();
    const attachmentResponses = await addAttachment(addAttachmentRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const attachmentResponses = await commentElement.addAttachment(addAttachmentRequest);

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const addAttachmentRequest = {
      annotationId: 'ANNOTATION_ID',
      files: '<Files[]>'
    };

    const commentElement = Velt.getCommentElement();
    const attachmentResponses = await commentElement.addAttachment(addAttachmentRequest);
    ```
  </Tab>
</Tabs>

#### deleteAttachment

* Delete an attachment from a specific comment annotation
* Params: [DeleteAttachmentRequest](/api-reference/sdk/models/data-models#deleteattachmentrequest)
* Returns: Promise\<[DeleteAttachmentEvent](/api-reference/sdk/models/data-models#deleteattachmentevent) | null>

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const deleteAttachmentRequest = {
      annotationId: 'ANNOTATION_ID',
      commentId: COMMENT_ID,
      attachmentId: 'ATTACHMENT_ID'
    };

    // Hook
    const { deleteAttachment } = useDeleteAttachment();
    const deleteAttachmentEvent = await deleteAttachment(deleteAttachmentRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const deleteAttachmentEvent = await commentElement.deleteAttachment(deleteAttachmentRequest);

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const deleteAttachmentRequest = {
      annotationId: 'ANNOTATION_ID',
      commentId: COMMENT_ID,
      attachmentId: 'ATTACHMENT_ID'
    };

    const commentElement = Velt.getCommentElement();
    const deleteAttachmentEvent = await commentElement.deleteAttachment(deleteAttachmentRequest);
    ```
  </Tab>
</Tabs>

#### getAttachment

* Get attachments from a specific comment annotation
* Params: [GetAttachmentRequest](/api-reference/sdk/models/data-models#getattachmentrequest)
* Returns: Promise\<[Attachment\[\]](/api-reference/sdk/models/data-models#attachment)>

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const getAttachmentRequest = {
      annotationId: 'ANNOTATION_ID',
      commentId: COMMENT_ID,
    };

    // Hook
    const { getAttachment } = useGetAttachment();
    const attachments = await getAttachment(getAttachmentRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const attachments = await commentElement.getAttachment(getAttachmentRequest);

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const getAttachmentRequest = {
      annotationId: 'ANNOTATION_ID',
      commentId: COMMENT_ID,
    };

    const commentElement = Velt.getCommentElement();
    const attachments = await commentElement.getAttachment(getAttachmentRequest);
    ```
  </Tab>
</Tabs>

#### allowedFileTypes

Limit file types in comment attachments by specifying allowed file extensions.

Default: Not specified (all supported file types allowed)

When this property is set, users can only attach files with the specified extensions. This helps you maintain security standards and ensure only approved file types are shared in collaborative discussions.

By default, Velt supports `.png`, `.jpg`, `.gif` (static & animated), `.svg` file types up to 15MB per file. With `allowedFileTypes`, you can restrict to a subset of these or any other file extensions your application requires.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Using component prop
    <VeltComments allowedFileTypes={['jpg', 'png']} />
    ```

    ```jsx theme={null}
    // Using API method
    const commentElement = client.getCommentElement();
    commentElement.setAllowedFileTypes(['jpg', 'png']);
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <!-- Using HTML attribute -->
    <velt-comments allowed-file-types="['jpg', 'png']"></velt-comments>
    ```

    ```js theme={null}
    // Using API method
    const commentElement = Velt.getCommentElement();
    commentElement.setAllowedFileTypes(['jpg', 'png']);
    ```
  </Tab>
</Tabs>

#### attachmentNameInMessage

Display the attachment filename in the message when a file is attached.

Default: `false`

When this property is enabled, the attachment filename will appear in the message text when a user selects a file to attach. This provides immediate visual confirmation of which file they've attached to their comment, improving clarity before submitting.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments attachmentNameInMessage={true} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comments attachment-name-in-message="true"></velt-comments>
    ```
  </Tab>
</Tabs>

#### setComposerFileAttachments

Programmatically add file attachments to the comment composer from your application instead of requiring users to select files from the file system.

This method enables workflows where you want to attach files programmatically, such as:

* Attaching screenshots captured within your application
* Including generated reports or documents
* Adding files from your own storage system
* Pre-populating attachments based on user context

Params: [UploadFileData](/api-reference/sdk/models/data-models#uploadfiledata)

The `UploadFileData` object accepts the following properties:

* `files` (required): Array of File objects to attach to the comment composer
* `annotationId` (optional): ID of the target comment annotation. Use this to add attachments to an existing comment thread
* `targetElementId` (optional): ID of the target element where the comment composer is attached. Use this to add attachments to a specific element

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();

    // Add attachments to a new comment composer
    commentElement.setComposerFileAttachments({
    files: [file1, file2],
    });

    // Add attachments to an existing comment annotation
    commentElement.setComposerFileAttachments({
    files: [file1, file2],
    annotationId: 'annotation-123',
    });

    // Add attachments to a comment composer on a specific element
    commentElement.setComposerFileAttachments({
    files: [file1, file2],
    targetElementId: 'element-456',
    });

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const commentElement = Velt.getCommentElement();

    // Add attachments to a new comment composer
    commentElement.setComposerFileAttachments({
      files: [file1, file2],
    });

    // Add attachments to an existing comment annotation
    commentElement.setComposerFileAttachments({
      files: [file1, file2],
      annotationId: 'annotation-123',
    });

    // Add attachments to a comment composer on a specific element
    commentElement.setComposerFileAttachments({
      files: [file1, file2],
      targetElementId: 'element-456',
    });
    ```
  </Tab>
</Tabs>

#### attachmentDownload

Control whether attachment downloads happen automatically when users click the download button.

Default: `true`

When enabled, clicking the download button on an attachment will automatically download the file. When disabled, the automatic download is prevented, and you can handle the download action with custom logic by subscribing to the `attachmentDownloadClicked` event.

This is useful for:

* Tracking download analytics before initiating the download
* Implementing custom download URLs or CDN routes
* Adding access control checks before allowing downloads

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Using component prop
    <VeltComments attachmentDownload={false} />
    ```

    ```jsx theme={null}
    // Using API methods
    const commentElement = client.getCommentElement();
    commentElement.enableAttachmentDownload();
    commentElement.disableAttachmentDownload();
    ```

    ```jsx theme={null}
    // Subscribe to download click events
    const commentElement = client.getCommentElement();
    commentElement.on('attachmentDownloadClicked').subscribe((event) => {
      // event.annotationId - ID of the comment annotation
      // event.commentAnnotation - Full comment annotation object
      // event.attachment - The attachment that was clicked
      // event.metadata - Event metadata

    // Implement custom download logic
    console.log('Attachment download clicked:', event.attachment);

    // Example: Custom analytics tracking
    trackDownload(event.attachment.id);

    // Example: Custom download URL
    window.open(event.attachment.url, '\_blank');
    });

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <!-- Using HTML attribute -->
    <velt-comments attachment-download="false"></velt-comments>
    ```

    ```js theme={null}
    // Using API methods
    const commentElement = Velt.getCommentElement();
    commentElement.enableAttachmentDownload();
    commentElement.disableAttachmentDownload();
    ```

    ```js theme={null}
    // Subscribe to download click events
    const commentElement = Velt.getCommentElement();
    commentElement.on("attachmentDownloadClicked").subscribe((event) => {
      // event.annotationId - ID of the comment annotation
      // event.commentAnnotation - Full comment annotation object
      // event.attachment - The attachment that was clicked
      // event.metadata - Event metadata

      // Implement custom download logic
      console.log("Attachment download clicked:", event.attachment);

      // Example: Custom analytics tracking
      trackDownload(event.attachment.id);

      // Example: Custom download URL
      window.open(event.attachment.url, "_blank");
    });
    ```
  </Tab>
</Tabs>

# Text Formatting

#### enableFormatOptions

Enable rich text formatting toolbar in comment composers. Users can apply bold, italic, underline, and strikethrough formatting.

Default: `false`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Using Component Props
    <VeltComments formatOptions={true} />

    // Using API methods
    const commentElement = client.getCommentElement();
    commentElement.enableFormatOptions();
    commentElement.disableFormatOptions();

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <!-- Using HTML attributes -->
    <velt-comments format-options="true"></velt-comments>

    <script>
    // Using API methods
    const commentElement = Velt.getCommentElement();
    commentElement.enableFormatOptions();
    commentElement.disableFormatOptions();
    </script>
    ```
  </Tab>
</Tabs>

#### setFormatConfig

Configure which format types are available in the formatting toolbar.

Params: [`FormatConfig`](/api-reference/sdk/models/data-models#formatconfig)

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Using Hooks
    const commentElement = useCommentUtils();
    commentElement.setFormatConfig({
      bold: { enable: true },
      italic: { enable: true },
      underline: { enable: false },
      strikethrough: { enable: false }
    });

    // Using API methods
    const commentElement = client.getCommentElement();
    commentElement.setFormatConfig({
    bold: { enable: true },
    italic: { enable: true },
    underline: { enable: false },
    strikethrough: { enable: false }
    });

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <script>
    const commentElement = Velt.getCommentElement();
    commentElement.setFormatConfig({
      bold: { enable: true },
      italic: { enable: true },
      underline: { enable: false },
      strikethrough: { enable: false }
    });
    </script>
    ```
  </Tab>
</Tabs>

# Reactions

#### enableReactions

<img src="https://mintcdn.com/velt/vGgIoGfoceFP8dEI/images/reactions.png?fit=max&auto=format&n=vGgIoGfoceFP8dEI&q=85&s=b6722120add1099a4b8663de34f4cfa1" alt="" width="1280" height="720" data-path="images/reactions.png" />

Whether emoji reactions are enabled.

Default: `true`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments reactions={true} />
    ```

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableReactions();
    commentElement.disableReactions();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    <velt-comments reactions="true"></velt-comments>
    ```

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableReactions();
    commentElement.disableReactions();
    ```
  </Tab>
</Tabs>

#### setCustomReactions

* You can set custom reactions by passing a map that contains information about the reactions you want to add.
* The map keys should be the reaction ID, and the map value should contain an object with either an `url` or `emoji` field to represent the reaction icon you want to use.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();

    const customReactions = {
      reactionId1: {
        emoji: "🤣", // This will default to system emoji
      },
      reactionId2: {
        emoji: "🎉", // This will default to system emoji
      },
      reactionId3: {
        emoji: "🚀", // This will default to system emoji
      },
    };
    commentElement.setCustomReactions(customReactions);
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();

    const customReactions = {
    "reactionId1": {
    "emoji": "🤣" // This will default to system emoji
    },
    "reactionId2": {
    "emoji": "🎉" // This will default to system emoji
    },
    "reactionId3": {
    "emoji": "🚀" // This will default to system emoji
    }
    }
    commentElement.setCustomReactions(customReactions);

    ```
  </Tab>
</Tabs>

#### addReaction

* Add a reaction to a specific comment annotation
* Params: [AddReactionRequest](/api-reference/sdk/models/data-models#addreactionrequest)
* Returns: Promise\<[AddReactionEvent](/api-reference/sdk/models/data-models#addreactionevent) | null>

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const addReactionRequest = {
      annotationId: '-OCWolieeXVOfPqTa0G-',
      commentId: 384399,
      reaction: {
        reactionId: 'fire',
        customReaction: {
              "emoji": "🔥"
        }
      }
    };

    // Hook
    const { addReaction } = useAddReaction();
    const addReactionEvent = await addReaction(addReactionRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const addReactionEvent = await commentElement.addReaction(addReactionRequest);
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const addReactionRequest = {
      annotationId: '-OCWolieeXVOfPqTa0G-',
      commentId: 384399,
      reaction: {
        reactionId: 'fire',
        customReaction: {
              "emoji": "🔥"
        }
      }
    };

    const commentElement = Velt.getCommentElement();
    const addReactionEvent = await commentElement.addReaction(addReactionRequest);

    ```
  </Tab>
</Tabs>

#### deleteReaction

* Delete a reaction from a specific comment annotation
* Params: [DeleteReactionRequest](/api-reference/sdk/models/data-models#deletereactionrequest)
* Returns: Promise\<[DeleteReactionEvent](/api-reference/sdk/models/data-models#deletereactionevent) | null>

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const deleteReactionRequest = {
      annotationId: '-OCWolieeXVOfPqTa0G-',
      commentId: 384399,
      reaction: {
        reactionId: 'fire'
      }
    };

    // Hook
    const { deleteReaction } = useDeleteReaction();
    const deleteReactionEvent = await deleteReaction(deleteReactionRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const deleteReactionEvent = await commentElement.deleteReaction(deleteReactionRequest);
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const deleteReactionRequest = {
      annotationId: '-OCWolieeXVOfPqTa0G-',
      commentId: 384399,
      reaction: {
        reactionId: 'fire'
      }
    };

    const commentElement = Velt.getCommentElement();
    const deleteReactionEvent = await commentElement.deleteReaction(deleteReactionRequest);

    ```
  </Tab>
</Tabs>

#### toggleReaction

* Toggle a reaction for a specific comment annotation
* Params: [ToggleReactionRequest](/api-reference/sdk/models/data-models#togglereactionrequest)
* Returns: Promise\<[ToggleReactionEvent](/api-reference/sdk/models/data-models#togglereactionevent) | null>

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const toggleReactionRequest = {
      annotationId: '-OCWolieeXVOfPqTa0G-',
      commentId: 384399,
      reaction: {
        reactionId: 'fire'
      }
    };

    // Hook
    const { toggleReaction } = useToggleReaction();
    const toggleReactionEvent = await toggleReaction(toggleReactionRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const toggleReactionEvent = await commentElement.toggleReaction(toggleReactionRequest);
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const toggleReactionRequest = {
      annotationId: '-OCWolieeXVOfPqTa0G-',
      commentId: 384399,
      reaction: {
        reactionId: 'fire'
      }
    };

    const commentElement = Velt.getCommentElement();
    const toggleReactionEvent = await commentElement.toggleReaction(toggleReactionRequest);

    ```
  </Tab>
</Tabs>

# Status & Priority

#### enableStatus

<img src="https://mintcdn.com/velt/gY7ilEx2g4g3-HVe/images/status-default.png?fit=max&auto=format&n=gY7ilEx2g4g3-HVe&q=85&s=d2b5d1dbc07f584abdb0f1f18408f52c" alt="" width="1280" height="720" data-path="images/status-default.png" />

Whether to enable the default status dropdown & filters.

`Default: true`

When this is on, users can assign a status to each comment & filter comment by status in the sidebar. You can customize the list of status options as shown below on this page.

<Tabs>
  <Tab title="React / Next.js">
    ```js theme={null}
    <VeltComments status={true} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    <velt-comments status="true"></velt-comments>
    ```
  </Tab>
</Tabs>

API Method:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableStatus();
    commentElement.disableStatus();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableStatus();
    commentElement.disableStatus();
    ```
  </Tab>
</Tabs>

#### setCustomStatus

<img src="https://mintcdn.com/velt/2O8vk8YlVD4Kq-ni/images/custom-status.png?fit=max&auto=format&n=2O8vk8YlVD4Kq-ni&q=85&s=ebf2ba52820edf0037c3975d1ec7d7b5" alt="" width="1280" height="720" data-path="images/custom-status.png" />

* With custom statuses, you can replace the default statuses with your own values.
* These statuses are also used in the comment sidebar to filter comments by status.
* There are three types of statuses:
  * `default`: This will be the default status assigned to each comment.
  * `ongoing`: This is treated as an intermediary status, you can add as many statuses with type ongoing as you want.
  * `terminal`: This represents a status that is completed. Comments with this status type are no longer shown in the DOM.
* Ensure that there are at least 2 statuses set.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.setCustomStatus([
      {
        id: 'open',
        name: 'Open',
        color: '#625df5',
        lightColor: '#f2f2fe',
        type: 'default',
      },
      {
        id: 'resolved',
        name: 'Resolved',
        color: '#198f65',
        lightColor: '#edf6f3',
        type: 'terminal',
      },
    ])
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.setCustomStatus([
      {
        id: 'open',
        name: 'Open',
        color: '#625df5',
        lightColor: '#f2f2fe',
        type: 'default',
      },
      {
        id: 'resolved',
        name: 'Resolved',
        color: '#198f65',
        lightColor: '#edf6f3',
        type: 'terminal',
      },
    ])
    ```
  </Tab>
</Tabs>

#### enableResolveButton

<img src="https://mintcdn.com/velt/vGgIoGfoceFP8dEI/images/resolve-button.png?fit=max&auto=format&n=vGgIoGfoceFP8dEI&q=85&s=b9a34780cbc2230ce217a6be496d5908" alt="" width="1280" height="720" data-path="images/resolve-button.png" />

Whether to show resolve button on comments.

`Default: true`

This adds a tick mark button on the top right corner of the comment dialog. Clicking on this button will mark the comment as resolved.

<Tabs>
  <Tab title="React / Next.js">
    ```js theme={null}
    <VeltComments resolveButton={true} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    <velt-comments resolve-button="true"></velt-comments>
    ```
  </Tab>
</Tabs>

API Method:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableResolveButton();
    commentElement.disableResolveButton();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableResolveButton();
    commentElement.disableResolveButton();
    ```
  </Tab>
</Tabs>

#### updateStatus

* Updates the status of a comment annotation.
* Params: [UpdateStatusRequest](/api-reference/sdk/models/data-models#updatestatusrequest)
* Returns: [UpdateStatusEvent](/api-reference/sdk/models/data-models#updatestatusevent)

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const updateStatusRequest = {
      annotationId: 'ANNOTATION_ID',
      status: {
        "id": "open",
        "name": "Open",
        "color": "white",
        "lightColor":"green",
        "type": "default"
      }
    };

    // Hook
    const { updateStatus } = useUpdateStatus();
    const updateStatusEvent = await updateStatus(updateStatusRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const updateStatusEvent = await commentElement.updateStatus(updateStatusRequest);

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const updateStatusRequest = {
      annotationId: 'ANNOTATION_ID',
      status: {
        "id": "open",
        "name": "Open",
        "color": "white",
        "lightColor":"green",
        "type": "default"
      }
    };

    const commentElement = Velt.getCommentElement();
    const updateStatusEvent = await commentElement.updateStatus(updateStatusRequest);
    ```
  </Tab>
</Tabs>

#### resolveCommentAnnotation

* Resolves a comment annotation
* Params: [ResolveCommentAnnotationRequest](/api-reference/sdk/models/data-models#resolvecommentannotationrequest)
* Returns: [ResolveCommentAnnotationEvent](/api-reference/sdk/models/data-models#resolvecommentannotationevent)

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const resolveCommentAnnotationRequest = {
      annotationId: 'ANNOTATION_ID'
    };

    // Hook
    const { resolveCommentAnnotation } = useResolveCommentAnnotation();
    const resolveCommentAnnotationEvent = await resolveCommentAnnotation(resolveCommentAnnotationRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const resolveCommentAnnotationEvent = await commentElement.resolveCommentAnnotation(resolveCommentAnnotationRequest);

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const resolveCommentAnnotationRequest = {
      annotationId: 'ANNOTATION_ID'
    };

    const commentElement = Velt.getCommentElement();
    const resolveCommentAnnotationEvent = await commentElement.resolveCommentAnnotation(resolveCommentAnnotationRequest);
    ```
  </Tab>
</Tabs>

#### enablePriority

<img src="https://mintcdn.com/velt/vGgIoGfoceFP8dEI/images/priority-default.png?fit=max&auto=format&n=vGgIoGfoceFP8dEI&q=85&s=cae4c4a67116529da6779d6a9382eb2b" alt="" width="1280" height="720" data-path="images/priority-default.png" />

Whether to enable setting priority on comments.

`Default: false`

When this is on, users can assign a priority to each comment & filter comment by priority in the sidebar. You can customize the list of priority options as shown later on this page in the Set Custom Priorities section.

<Tabs>
  <Tab title="React / Next.js">
    ```js theme={null}
    <VeltComments priority={true} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    <velt-comments priority="true"></velt-comments>
    ```
  </Tab>
</Tabs>

API Method:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enablePriority();
    commentElement.disablePriority();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enablePriority();
    commentElement.disablePriority();
    ```
  </Tab>
</Tabs>

#### setCustomPriority

<img src="https://mintcdn.com/velt/2O8vk8YlVD4Kq-ni/images/custom-priority.png?fit=max&auto=format&n=2O8vk8YlVD4Kq-ni&q=85&s=d2ed3a5ceeca1c57de076098187bfe2c" alt="" width="1280" height="720" data-path="images/custom-priority.png" />

<Tabs>
  <Tab title="React / Next.js">
    Pass custom priorities in the `customPriority` prop.

    `Default priorities: P0, P1, P2`

    With custom priorities, you can replace the default priorities with your own values. These priorities are also used in the comment sidebar to filter comments by priority.

    This will work if you have enabled the priority feature.

    The `color` property is used to set the priority pill background color.

    The `lightColor` property sets the background color of the filter.

    ```js theme={null}
    <VeltComments
      customPriority={[
        {
          id: "low",
          name: "Low",
          color: "red",
          lightColor: "pink",
        },
      ]}
    />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    Pass custom priorities in the `custom-priority`.

    `Default priorities: P0, P1, P2`

    With custom priorities, you can replace the default priorities with your own values. These priorities are also used in the comment sidebar to filter comments by priority.

    This will work if you have enabled the priority feature.

    The `color` property is used to set the priority pill background color.

    The `lightColor` property sets the background color of the filter.

    ```js theme={null}
    <velt-comments
      custom-priority='[
      {
        "id": "low",
        "name": "Low",
        "color": "red",
        "lightColor": "pink",
      }
    ]'
    ></velt-comments>
    ```
  </Tab>
</Tabs>

API Method:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.setCustomPriority([
      {
        "id": "low",
        "name": "Low",
        "color": "red",
        "lightColor": "pink",
      },
    ])
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.setCustomPriority([
      {
        "id": "low",
        "name": "Low",
        "color": "red",
        "lightColor": "pink",
      },
    ])
    ```
  </Tab>
</Tabs>

<Warning>Make sure to have at least 2 categories set.</Warning>

#### updatePriority

* Updates the priority of a comment annotation
* Params: [UpdatePriorityRequest](/api-reference/sdk/models/data-models#updatepriorityrequest)
* Returns: [UpdatePriorityEvent](/api-reference/sdk/models/data-models#updatepriorityevent)

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const updatePriorityRequest = {
      annotationId: 'ANNOTATION_ID',
      priority: {
        "id": "low",
        "name": "Low",
        "color": "red",
        "lightColor": "pink",
      }
    };

    // Hook
    const { updatePriority } = useUpdatePriority();
    const updatePriorityEvent = await updatePriority(updatePriorityRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const updatePriorityEvent = await commentElement.updatePriority(updatePriorityRequest);

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const updatePriorityRequest = {
      annotationId: 'ANNOTATION_ID',
      priority: {
        "id": "low",
        "name": "Low",
        "color": "red",
        "lightColor": "pink",
      }
    };

    const commentElement = Velt.getCommentElement();
    const updatePriorityEvent = await commentElement.updatePriority(updatePriorityRequest);
    ```
  </Tab>
</Tabs>

# Recording

#### deleteRecording

* Delete a recording from a specific comment annotation
* Params: [DeleteRecordingRequest](/api-reference/sdk/models/data-models#deleterecordingrequest)
* Returns: Promise\<[DeleteRecordingEvent](/api-reference/sdk/models/data-models#deleterecordingevent) | null>

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const deleteRecordingRequest = {
      annotationId: 'ANNOTATION_ID',
      commentId: COMMENT_ID,
      recordingId: 'RECORDING_ID'
    };

    // Hook
    const { deleteRecording } = useDeleteRecording();
    const deleteRecordingEvent = await deleteRecording(deleteRecordingRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const deleteRecordingEvent = await commentElement.deleteRecording(deleteRecordingRequest);

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const deleteRecordingRequest = {
      annotationId: 'ANNOTATION_ID',
      commentId: COMMENT_ID,
      recordingId: 'RECORDING_ID'
    };

    const commentElement = Velt.getCommentElement();
    const deleteRecordingEvent = await commentElement.deleteRecording(deleteRecordingRequest);
    ```
  </Tab>
</Tabs>

#### getRecording

* Get recordings from a specific comment annotation
* Params: [GetRecordingRequest](/api-reference/sdk/models/data-models#getrecordingrequest)
* Returns: Promise\<[RecordedData\[\]](/api-reference/sdk/models/data-models#recordeddata)>

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const getRecordingRequest = {
      annotationId: 'ANNOTATION_ID',
      commentId: COMMENT_ID
    };

    // Hook
    const { getRecording } = useGetRecording();
    const recordings = await getRecording(getRecordingRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const recordings = await commentElement.getRecording(getRecordingRequest);

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const getRecordingRequest = {
      annotationId: 'ANNOTATION_ID',
      commentId: COMMENT_ID
    };

    const commentElement = Velt.getCommentElement();
    const recordings = await commentElement.getRecording(getRecordingRequest);
    ```
  </Tab>
</Tabs>

#### setAllowedRecordings

<img src="https://mintcdn.com/velt/vGgIoGfoceFP8dEI/images/recorder.png?fit=max&auto=format&n=vGgIoGfoceFP8dEI&q=85&s=19dc5bb17927fa6c802f26d1777694d9" alt="" width="1280" height="720" data-path="images/recorder.png" />

Set the Recorder media options within Comments: (`audio`, `screen`, `video`, `all`).

* `audio`: enables audio recording
* `screen`: enables screen recording
* `video`: enables video recording
* `all`: enables all recording options
* `none`: disables all recording options

Default: `"audio"`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments recordings="video,screen" />
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.setAllowedRecordings("video"); // set video mode only
    commentElement.setAllowedRecordings("audio,screen"); // set audio and screen mode only
    commentElement.setAllowedRecordings("all"); // set all modes
    commentElement.setAllowedRecordings("none"); // disable all modes
    ```
  </Tab>

  **Using Props:**

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    <velt-comments recordings="video,screen"></velt-comments>
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.setAllowedRecordings("video"); // set video mode only
    commentElement.setAllowedRecordings("audio,screen"); // set audio and screen mode only
    commentElement.setAllowedRecordings("all"); // set all modes
    commentElement.setAllowedRecordings("none"); // disable all modes
    ```
  </Tab>
</Tabs>

#### enableRecordingCountdown

<img src="https://mintcdn.com/velt/gAz_vLsG-ukKamYM/gifs/recording-countdown.gif?s=afe80f49d30b287196175210d8a9f275" alt="" width="2560" height="1440" data-path="gifs/recording-countdown.gif" />

Whether the Recorder countdown is enabled.

Default: `true`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments recordingCountdown={false} />
    ```

    ```jsx theme={null}
    const recorderElement = client.getRecorderElement();
    recorderElement.enableRecordingCountdown();
    recorderElement.disableRecordingCountdown();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    <velt-comments recording-countdown="false"></velt-comments>
    ```

    ```jsx theme={null}
    const recorderElement = Velt.getRecorderElement();
    recorderElement.enableRecordingCountdown();
    recorderElement.disableRecordingCountdown();
    ```
  </Tab>
</Tabs>

#### enableRecordingTranscription

Controls whether to enable AI transcription for recordings.

Default: `enabled`

<Tabs>
  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments recordingTranscription={false} />
    ```

    **Using API Methods:**

    ```javascript theme={null}
    // Using comment element
    const commentElement = client.getCommentElement();
    commentElement.enableRecordingTranscription();
    commentElement.disableRecordingTranscription();

    // Or using recorder element
    const recorderElement = client.getRecorderElement();
    recorderElement.enableRecordingTranscription();
    recorderElement.disableRecordingTranscription();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using Props:**

    ```html theme={null}
    <velt-comments recording-transcription="false"></velt-comments>
    ```

    **Using API Methods:**

    ```javascript theme={null}
    // Using comment element
    const commentElement = Velt.getCommentElement();
    commentElement.enableRecordingTranscription();
    commentElement.disableRecordingTranscription();

    // Or using recorder element
    const recorderElement = Velt.getRecorderElement();
    recorderElement.enableRecordingTranscription();
    recorderElement.disableRecordingTranscription();
    ```
  </Tab>
</Tabs>

# Deep Link

#### getLink

* Get a link to a specific comment annotation
* Params: [GetLinkRequest](/api-reference/sdk/models/data-models#getlinkrequest)
* Returns: [GetLinkResponse](/api-reference/sdk/models/data-models#getlinkresponse)

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const getLinkRequest = {
      annotationId: 'ANNOTATION_ID'
    };

    // Hook
    const { getLink } = useGetLink();
    const getLinkResponse = await getLink(getLinkRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const getLinkResponse = await commentElement.getLink(getLinkRequest);

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const getLinkRequest = {
      annotationId: 'ANNOTATION_ID'
    };

    const commentElement = Velt.getCommentElement();
    const getLinkResponse = await commentElement.getLink(getLinkRequest);
    ```
  </Tab>
</Tabs>

#### copyLink

* Copy a link to a specific comment annotation to clipboard
* Params: [CopyLinkRequest](/api-reference/sdk/models/data-models#copylinkrequest)
* Returns: [CopyLinkEvent](/api-reference/sdk/models/data-models#copylinkevent)

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const copyLinkRequest = {
      annotationId: 'ANNOTATION_ID'
    };

    // Hook
    const { copyLink } = useCopyLink();
    const copyLinkEvent = await copyLink(copyLinkRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const copyLinkEvent = await commentElement.copyLink(copyLinkRequest);

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const copyLinkRequest = {
      annotationId: 'ANNOTATION_ID'
    };

    const commentElement = Velt.getCommentElement();
    const copyLinkEvent = await commentElement.copyLink(copyLinkRequest);
    ```
  </Tab>
</Tabs>

# Navigation

#### scrollToCommentByAnnotationId

<img src="https://mintcdn.com/velt/gAz_vLsG-ukKamYM/gifs/scroll-on-click.gif?s=a495b786a84e9d17ad543b46a44d7487" alt="" width="2560" height="1440" data-path="gifs/scroll-on-click.gif" />

* This will scroll the page to the element directly. This will work if the element is present on the DOM.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.scrollToCommentByAnnotationId("annotationId");
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.scrollToCommentByAnnotationId('annotationId');
    ```
  </Tab>
</Tabs>

#### selectCommentByAnnotationId

* Use this to programmatically select a comment annotation by its ID.
* When called without arguments or with an invalid ID, it will close the currently selected annotation.
* Example: If the user opens a comment URL from an email notification, you can use this to open the comment dialog after your page has finished rendering.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Using Hooks
    const commentElement = useCommentUtils();

    // Open a specific annotation
    commentElement.selectCommentByAnnotationId("COMMENT_ANNOTATION_ID");

    // Close the currently selected annotation
    commentElement.selectCommentByAnnotationId();
    commentElement.selectCommentByAnnotationId("invalid-id");

    // Using API methods
    const commentElement = client.getCommentElement();

    // Open a specific annotation
    commentElement.selectCommentByAnnotationId("COMMENT_ANNOTATION_ID");

    // Close the currently selected annotation
    commentElement.selectCommentByAnnotationId();
    commentElement.selectCommentByAnnotationId("invalid-id");
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();

    // Open a specific annotation
    commentElement.selectCommentByAnnotationId('COMMENT_ANNOTATION_ID');

    // Close the currently selected annotation
    commentElement.selectCommentByAnnotationId();
    commentElement.selectCommentByAnnotationId('invalid-id');

    ```
  </Tab>
</Tabs>

#### onCommentSelectionChange

<Tabs>
  <Tab title="React / Next.js with Hooks">
    The `useCommentSelectionChangeHandler` hook can be used to subscribe to Comment selection changes.

    ```jsx theme={null}
    import React, { useEffect } from 'react';
    import { useCommentSelectionChangeHandler } from '@veltdev/react';

    function YourComponent() {
        const commentSelectionChange = useCommentSelectionChangeHandler();

        useEffect(() => {
            console.log('commentSelectionChange', commentSelectionChange);
        }, [commentSelectionChange]);

        return (
            <>
                Selected Comment: {commentSelectionChange.annotation.id}
            </>
        );
    }
    ```
  </Tab>

  <Tab title="React / Next.js">
    The `onCommentSelectionChange()` method can be used to listen Comment selection changes.

    ````jsx theme={null}
    const onCommentSelectionChange = (data) => {
      console.log('onCommentSelectionChange', data);
    }

    <VeltComments
      onCommentSelectionChange={(data) => onCommentSelectionChange(data)}
    />
    ``` Callback response schema:

    ```jsx
    export class CommentSelectionChangeData {
      selected!: boolean;
      annotation!: CommentAnnotation;
    }
    ````

    **API Methods:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    let subscription = commentElement
      .onCommentSelectionChange()
      .subscribe((data) => {
        console.log("onCommentSelectionChange: ", data);
      });
    ```

    **To unsubscribe from the subscription:**

    ```jsx theme={null}
    subscription?.unsubscribe();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    The `onCommentSelectionChange()` method can be used to listen Comment selection changes.

    ```jsx theme={null}
    <velt-comments></velt-comments>
    <script>
    const commentTag = document.querySelector('velt-comments');
    commentTag.addEventListener('onCommentSelectionChange', (event) => {
    	console.log('onCommentSelectionChange event', event.detail);
    });
    </script>
    ```

    **Callback response schema:**

    ```jsx theme={null}
    export class CommentSelectionChangeData {
      selected!: boolean;
      annotation!: CommentAnnotation;
    }
    ```

    **API Methods:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    let subscription = commentElement
      .onCommentSelectionChange()
      .subscribe((data) => {
        console.log("onCommentSelectionChange: ", data);
      });
    ```

    **To unsubscribe from the subscription:**

    ```jsx theme={null}
    subscription?.unsubscribe();
    ```
  </Tab>
</Tabs>

#### enablescrollToComment

<img src="https://mintcdn.com/velt/gAz_vLsG-ukKamYM/gifs/scroll-on-click.gif?s=a495b786a84e9d17ad543b46a44d7487" alt="" width="2560" height="1440" data-path="gifs/scroll-on-click.gif" />

Whether, users will be scrolled to the location of a `Comment` when it is clicked.

`Default: true`

By default, users will be redirected to a `Comment` if the comment id is provided in the url. But sometimes this experience is annoying, so we have provided a way to disable the option to automatically scroll users to the location of the `Comment`.

<Tabs>
  <Tab title="React / Next.js">
    To disable the feature, set `scrollToComment` to `false`.

    ```html theme={null}
    <VeltComments scrollToComment={false}/>
    ```
  </Tab>

  <Tab title="Other Frameworks">
    To disable the feature, set `scroll-to-comment` to `false`.

    ```html theme={null}
    <velt-comments scroll-to-comment="false"></velt-comments>
    ```
  </Tab>
</Tabs>

API methods:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    // To enable scroll to component
    commentElement.enablescrollToComment();
    // To disable scroll to component
    commentElement.disablescrollToComment();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    // To enable scroll to component
    commentElement.enablescrollToComment();
    // To disable scroll to component
    commentElement.disablescrollToComment();
    ```
  </Tab>
</Tabs>

# DOM Controls

#### allowedElementIds

#### allowedElementClassNames

#### allowedElementQuerySelectors

<img src="https://mintcdn.com/velt/gAz_vLsG-ukKamYM/gifs/comment-area.gif?s=d7da9f6110476805cd9c0addee8ffeee" alt="" width="2560" height="1440" data-path="gifs/comment-area.gif" />

Provide a list of element DOM IDs, class names, or query selectors where commenting should be allowed.

Comments will be disabled for all other elements. Note, this does not impact `Popover` mode.

<Tabs>
  <Tab title="React / Next.js">
    **Using Props:**

    ```js theme={null}
    <VeltComments 
      allowedElementIds={['some-element']} 
      allowedElementClassNames={["class-name-1", "class-name-2"]}
      allowedElementQuerySelectors={["#id1.class-name-1"]}
    />
    ```

    **Using API Method:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.allowedElementIds(["some-element"]);
    commentElement.allowedElementClassNames(["class-name-1", "class-name-2"]);
    commentElement.allowedElementQuerySelectors(["#id1.class-name-1"]);
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using Props:**

    ```html theme={null}
    <velt-comments 
      allowed-element-ids='["some-element"]'
      allowed-element-class-names='["class-name-1", "class-name-2"]'
      allowed-element-query-selectors='["#id1.class-name-1"]'
    >

    </velt-comments>
    ```

    **Using API Method:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.allowedElementIds(["some-element"]);
    commentElement.allowedElementClassNames(["class-name-1", "class-name-2"]);
    commentElement.allowedElementQuerySelectors(["#id1.class-name-1"]);
    ```
  </Tab>
</Tabs>

#### data-velt-comment-disabled

<img src="https://mintcdn.com/velt/gAz_vLsG-ukKamYM/gifs/comment-area.gif?s=d7da9f6110476805cd9c0addee8ffeee" alt="" width="2560" height="1440" data-path="gifs/comment-area.gif" />

Disable certain elements from being commented on.

Add the `data-velt-comment-disabled` attribute to elements where you want to disable commenting.

```html theme={null}
<div data-velt-comment-disabled></div>
```

#### sourceId

* When you have multiple elements with the same DOM ID, you can use the `sourceId` attribute to control which element displays the comment dialog when adding a new comment.
* By default, comments appear on all matching elements.
* This is useful in cases where you have multiple instances of the same data component on a page and want the comment to appear on each instance, such as Popover comments on a table.
* You can randomly generate the `sourceId`. It just needs to be unique for each element in the current session.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltCommentTool sourceId="sourceId1" />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comment-tool source-id="sourceId1"></velt-comment-tool>
    ```
  </Tab>
</Tabs>

# AI Categorization

#### enableAutoCategorize

<img src="https://mintcdn.com/velt/gAz_vLsG-ukKamYM/images/ai-categories.png?fit=max&auto=format&n=gAz_vLsG-ukKamYM&q=85&s=e05f5f3d9a6ab3c9b650e6d5d4da0944" alt="" width="1280" height="720" data-path="images/ai-categories.png" />

Whether AI auto-categorization of comments is enabled.

`Default: false`

We use AI to analyze your comment content and auto-categorize it so users can filter comments easily. You can provide a list of custom categories that we should use to categorize the comments (shown below).

<Tabs>
  <Tab title="React / Next.js">
    ```js theme={null}
    <VeltComments autoCategorize={true} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    <velt-comments auto-categorize="true"></velt-comments>
    ```
  </Tab>
</Tabs>

API Method:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableAutoCategorize();
    commentElement.disableAutoCategorize();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableAutoCategorize();
    commentElement.disableAutoCategorize();
    ```
  </Tab>
</Tabs>

#### setCustomCategory

<img src="https://mintcdn.com/velt/2O8vk8YlVD4Kq-ni/images/custom-categories.png?fit=max&auto=format&n=2O8vk8YlVD4Kq-ni&q=85&s=e893ecf769a2264a46e8a8f15662e1ca" alt="" width="1280" height="720" data-path="images/custom-categories.png" />

<Tabs>
  <Tab title="React / Next.js">
    Pass custom categories in the `customCategory` prop.

    `Default categories: Question, Feedback, Bug, Other.`

    With custom categories, you can replace the default categories with your own values.

    These categories are used in the `Comments Sidebar` to filter comments by category. The AI `autoCategorize` feature uses the list of categories to determine the closest category to choose from.

    The input format to the `customCategory` prop should be an array of objects with an `id`, `name`, and `color`.

    The `color` property is used to set the category pill background color.

    ```js theme={null}
    <VeltComments
      customCategory={[
        {
          id: "bug",
          name: "Bug",
          color: "red",
        },
      ]}
    />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    Pass custom categories in the `custom-category`.

    `Default categories: Question, Feedback, Bug, Other.`

    With custom categories, you can replace the default categories with your own values.

    These categories are used in the `Comments Sidebar` to filter comments by category. The AI `auto-categorize` uses the list of categories to determine the closest category to choose from.

    The input format to the `custom-category` should be an array of objects with an `id`, `name`, and `color`.

    The `color` property is used to set the category pill background color.

    ```js theme={null}
    <velt-comments
      customCategory='[
      {
        "id": "bug",
        "name": "Bug",
        "color": "red"
      }
    ]'
    ></velt-comments>
    ```
  </Tab>
</Tabs>

API Method:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.setCustomCategory([
      {
        "id": "bug",
        "name": "Bug",
        "color": "red"
      }
    ])
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.setCustomCategory([
      {
        id: "bug",
        name: "Bug",
        color: "red",
      },
    ]);
    ```
  </Tab>
</Tabs>

<Warning>
  Make sure to have at least 2 categories set.
</Warning>

# UI/UX

#### composerMode

By default, the `Composer` in the `Comments Dialog` only shows the text input box and does not show the actions bar until the `Composer` is clicked on or the user starts typing.

You can modify this behavior by setting the `Composer Mode` prop to `"expanded"`. This will make the actions bar always visible.

To keep the default behavior you can set the property to `"default"`.

`Default: "default"`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments composerMode="expanded" />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    <velt-comments composer-mode="expanded"></velt-comments>
    ```
  </Tab>
</Tabs>

#### commentToNearestAllowedElement

Attach comment pins to the closest allowed element when clicking on a non-allowed element.
Default: `false`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments commentToNearestAllowedElement={true} />
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableCommentToNearestAllowedElement();
    commentElement.disableCommentToNearestAllowedElement();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comments comment-to-nearest-allowed-element="true"></velt-comments>
    ```

    **Using API:**

    ```js theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableCommentToNearestAllowedElement();
    commentElement.disableCommentToNearestAllowedElement();
    ```
  </Tab>
</Tabs>

#### deleteThreadWithFirstComment

Whether deleting the first comment in a thread will delete the entire thread.

Default: `true`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments deleteThreadWithFirstComment={false} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comments delete-thread-with-first-comment="false"></velt-comments>
    ```
  </Tab>
</Tabs>

#### draftMode

Whether to store comments in draft if they are not submitted.

When enabled, partial comments are preserved when the dialog closes, including composer text, attachments, and recordings.

Default: `true`

**Behavior:**

* Partial comments are saved with `isDraft: true` when the dialog is closed
* The dialog shows a shake animation on the first click outside if there's unsaved content
* The `data-velt-annotation-draft` attribute is set on dialogs with unsaved content for custom styling

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments draftMode={false} />
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableDraftMode();
    commentElement.disableDraftMode();
    ```
  </Tab>

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

    **Using API:**

    ```js theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableDraftMode();
    commentElement.disableDraftMode();
    ```
  </Tab>
</Tabs>

#### enableCollapsedComments

You can control whether comments inside the annotation should be collapsed.

`Default: false`

<Tabs>
  <Tab title="React / Next.js">
    Using Props:

    ```jsx theme={null}
    <VeltComments collapsedComments={true} />
    ```

    Using API:

    ```javascript theme={null}
    const commentElement = client.getCommentElement();
    // To enable collapsed comments
    commentElement.enableCollapsedComments();
    // To disable collapsed comments
    commentElement.disableCollapsedComments();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    Using Props:

    ```html theme={null}
    <velt-comments collapsed-comments="true"></velt-comments>
    ```

    Using API:

    ```javascript theme={null}
    const commentElement = Velt.getCommentElement();
    // To enable collapsed comments
    commentElement.enableCollapsedComments();
    // To disable collapsed comments
    commentElement.disableCollapsedComments();
    ```
  </Tab>
</Tabs>

#### enableFullExpanded

* You can control whether comments should be shown in fully expanded state by default.
* Available on all comment-related components and can be controlled via props or API methods.

`Default: false`

<Tabs>
  <Tab title="React / Next.js">
    Using Props:

    ```jsx theme={null}
    // Apply this change globally to all types of comments
    <VeltComments fullExpanded={true} />

    // Apply this change only in comments sidebar

    <VeltCommentsSidebar fullExpanded={true} />

    // Apply this change only in inline comments section

    <VeltInlineCommentsSection fullExpanded={true} />

    // Apply this change only in the standalone comment thread

    <VeltCommentThread fullExpanded={true} />

    ```

    Using API:

    ```js theme={null}
    // API Method
    const commentElement = client.getCommentElement();
    commentElement.enableFullExpanded();
    commentElement.disableFullExpanded();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    Using Props:

    ```html theme={null}
    <!-- Apply this change globally to all types of comments -->
    <velt-comments full-expanded="true"></velt-comments>

    <!-- Apply this change only in comments sidebar -->

    <velt-comments-sidebar full-expanded="true"></velt-comments-sidebar>

    <!-- Apply this change only in inline comments section -->

    <velt-inline-comments-section full-expanded="true"></velt-inline-comments-section>

    <!-- Apply this change only in the standalone comment thread -->

    <velt-comment-thread full-expanded="true"></velt-comment-thread>

    ```

    Using API:

    ```js theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableFullExpanded();
    commentElement.disableFullExpanded();
    ```
  </Tab>
</Tabs>

#### enableShortUserName

You can control whether long user names should be shortened. For long names, this will first create an initial of the second name and if the name is still long, it will truncate it with ellipses.

Default: `true`

<Tabs>
  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments shortUserName={false} />
    ```

    **Using API:**

    ```javascript theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableShortUserName();
    commentElement.disableShortUserName();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using Props:**

    ```html theme={null}
    <velt-comments short-user-name="false"></velt-comments>
    ```

    **Using API:**

    ```javascript theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableShortUserName();
    commentElement.disableShortUserName();
    ```
  </Tab>
</Tabs>

#### enableSignInButton

<img src="https://mintcdn.com/velt/gY7ilEx2g4g3-HVe/images/sign-in-button.png?fit=max&auto=format&n=gY7ilEx2g4g3-HVe&q=85&s=889a09f02a9a9bd1a51c61a8044e9077" alt="" width="1280" height="720" data-path="images/sign-in-button.png" />

Whether to enable Sign In button on comment dialog when user is anonymous or signed out.

`Default: false`

This allows anonymous or signed out users to still read the comments but encourages them to sign in if they want to respond to the comments.

<Tabs>
  <Tab title="React / Next.js">
    ```js theme={null}
    <VeltComments signInButton={true} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    <velt-comments sign-in-button="true"></velt-comments>
    ```
  </Tab>
</Tabs>

API Method:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableSignInButton();
    commentElement.disableSignInButton();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableSignInButton();
    commentElement.disableSignInButton();
    ```
  </Tab>
</Tabs>

#### enableSidebarButtonOnCommentDialog

<img src="https://mintcdn.com/velt/gY7ilEx2g4g3-HVe/images/sidebar-button-on-comment-dialog.png?fit=max&auto=format&n=gY7ilEx2g4g3-HVe&q=85&s=6b5a81b9667f77d96428759d5a819a86" alt="" width="1280" height="720" data-path="images/sidebar-button-on-comment-dialog.png" />

Whether the Sidebar Button on Comment Dialogs show up.

`Default: true`

By Default, each Comment Dialog has a button at the bottom that will open the Comments Sidebar when clicked.

To disable it, you can set it to false:

<Tabs>
  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments sidebarButtonOnCommentDialog={true} />
    ```

    **Using API methods:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableSidebarButtonOnCommentDialog();
    commentElement.disableSidebarButtonOnCommentDialog();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using Props:**

    ```jsx theme={null}
    <velt-comments sidebar-button-comment-dialog="true"></velt-comments>
    ```

    **Using API methods:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableSidebarButtonOnCommentDialog();
    commentElement.disableSidebarButtonOnCommentDialog();
    ```
  </Tab>
</Tabs>

#### enableDeleteReplyConfirmation

You can enable a confirmation dialog before deleting a reply in comment threads. This feature helps prevent accidental deletions and improves user experience.

<Tabs>
  <Tab title="React / Next.js">
    Using Props:

    ```jsx theme={null}
    <VeltComments deleteReplyConfirmation={true} />
    ```

    Using API:

    ```javascript theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableDeleteReplyConfirmation();
    commentElement.disableDeleteReplyConfirmation();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    Using Props:

    ```html theme={null}
    <velt-comments delete-reply-confirmation="true"></velt-comments>
    ```

    Using API:

    ```javascript theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableDeleteReplyConfirmation();
    commentElement.disableDeleteReplyConfirmation();
    ```
  </Tab>
</Tabs>

#### enableMobileMode

<img src="https://mintcdn.com/velt/vGgIoGfoceFP8dEI/images/mobile-mode.png?fit=max&auto=format&n=vGgIoGfoceFP8dEI&q=85&s=e70906b207c4c2f318f7cfdb7f4a8510" alt="" width="1280" height="720" data-path="images/mobile-mode.png" />

<img src="https://mintcdn.com/velt/vGgIoGfoceFP8dEI/images/mobile-mode-composer.png?fit=max&auto=format&n=vGgIoGfoceFP8dEI&q=85&s=4f0119d1f599a775d4e1deee0c2009c2" alt="" width="1280" height="720" data-path="images/mobile-mode-composer.png" />

Whether mobile mode is enabled.

When mobile mode is enabled and the screen width is small enough, comment windows will appear fixed to the bottom of the screen and full width instead of the usual popup window.

`Default: false`

<Tabs>
  <Tab title="React / Next.js">
    ```js theme={null}
    <VeltComments mobileMode={true} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    <velt-comments mobile-mode="true"></velt-comments>
    ```
  </Tab>
</Tabs>

API Method:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableMobileMode();
    commentElement.disableMobileMode();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableMobileMode();
    commentElement.disableMobileMode();
    ```
  </Tab>
</Tabs>

#### enableCommentPinHighlighter

<img src="https://mintcdn.com/velt/vGgIoGfoceFP8dEI/images/pin-highlighter-outline.png?fit=max&auto=format&n=vGgIoGfoceFP8dEI&q=85&s=8c363c925a3a675679053f5f5715529b" alt="" width="1280" height="720" data-path="images/pin-highlighter-outline.png" />

Wheter the pin highlighter outline is enabled or not.

`Default: true`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments commentPinHighlighter={false} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    <velt-comments comment-pin-highlighter="false"></velt-comments>
    ```
  </Tab>
</Tabs>

API Methods:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableCommentPinHighlighter(); // to enable comment pin highlight
    commentElement.disableCommentPinHighlighter(); // to disable comment pin highlight
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableCommentPinHighlighter(); // to enable comment pin highlight
    commentElement.disableCommentPinHighlighter(); // to disable comment pin highlight
    ```
  </Tab>
</Tabs>

#### pinDrag

Whether comment pins can be dragged to reposition them.

`Default: true`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments pinDrag={false} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    <velt-comments pin-drag="false"></velt-comments>
    ```
  </Tab>
</Tabs>

API Methods:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enablePinDrag(); // to enable comment pin drag
    commentElement.disablePinDrag(); // to disable comment pin drag
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enablePinDrag(); // to enable comment pin drag
    commentElement.disablePinDrag(); // to disable comment pin drag
    ```
  </Tab>
</Tabs>

#### enableDialogOnHover

<img src="https://mintcdn.com/velt/gAz_vLsG-ukKamYM/gifs/show-dialog-on-hover.gif?s=4c58970e8c5d6185fd6955cfa9e865df" alt="" width="2400" height="1300" data-path="gifs/show-dialog-on-hover.gif" />

Whether the comment dialog shows on hover over the comment pin or the target element.

`Default: true`

<Tabs>
  <Tab title="React / Next.js">
    ```js theme={null}
    <VeltComments dialogOnHover={true} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    <velt-comments dialog-on-hover="true"></velt-comments>
    ```
  </Tab>
</Tabs>

API Method:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableDialogOnHover();
    commentElement.disableDialogOnHover();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableDialogOnHover();
    commentElement.disableDialogOnHover();
    ```
  </Tab>
</Tabs>

#### enableFloatingCommentDialog

<img src="https://mintcdn.com/velt/gAz_vLsG-ukKamYM/gifs/floating-comment-dialog.gif?s=21a58debadd5a1d8eca880200bcc03d9" alt="" width="1200" height="650" data-path="gifs/floating-comment-dialog.gif" />

Whether floating comment dialog is shown next to comment pin on hover or click.

`Default: true`

<Tabs>
  <Tab title="React / Next.js">
    ```js theme={null}
    <VeltComments floatingCommentDialog={true} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    <velt-comments floating-comment-dialog="true"></velt-comments>
    ```
  </Tab>
</Tabs>

API Method:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableFloatingCommentDialog();
    commentElement.disableFloatingCommentDialog();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableFloatingCommentDialog();
    commentElement.disableFloatingCommentDialog();
    ```
  </Tab>
</Tabs>

#### excludeLocationIds

Use this to filter out Comments at a specific Location for certain Users.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const locationIds = ['location1', 'location2']; // list of location ids
    client.excludeLocationIds(locationIds);
    ```

    To reset it, you can pass an empty array:

    ```jsx theme={null}
    client.excludeLocationIds([]);
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const locationIds = ['location1', 'location2']; // list of location ids
    Velt.excludeLocationIds(locationIds);
    ```

    To reset it, you can pass an empty array:

    ```jsx theme={null}
    Velt.excludeLocationIds([]);
    ```
  </Tab>
</Tabs>

#### enableReplyAvatars

This shows the avatars of unique users who have replied to a comment.

* `replyAvatars`: Whether the reply avatar component is enabled.
* `maxReplyAvatars`: The maximum number of reply avatars to show. It will show the count of remaining unque users as the next avatar.

`Default: false`

<Tabs>
  <Tab title="React / Next.js">
    **Using props:**

    ```jsx theme={null}
    <VeltComments maxReplyAvatars={2} replyAvatars={true} />
    ```

    **Using API:**

    ```jsx theme={null}
    const commentsElement = client.getCommentElement();
    commentsElement.enableReplyAvatars(); // Enables the reply avatar component.
    commentsElement.disableReplyAvatars(); // Disables the reply avatar component.
    commentsElement.setMaxReplyAvatars(2); // Sets the maximum number of reply avatars to show.
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using props:**

    ```html theme={null}
    <velt-comments max-reply-avatars="2" reply-avatars="true"></velt-comments>
    ```

    **Using API:**

    ```jsx theme={null}
    const commentsElement = Velt.getCommentElement();
    commentsElement.enableReplyAvatars(); // Enables the reply avatar component.
    commentsElement.disableReplyAvatars(); // Disables the reply avatar component.
    commentsElement.setMaxReplyAvatars(2); // Sets the maximum number of reply avatars to show.
    ```
  </Tab>
</Tabs>

#### filterCommentsOnDom

* Filter out comments in the DOM when they are filtered in the sidebar.
* When the sidebar is closed (default mode) or unmounted (embed mode), the DOM filter will be removed.

`Default: false`

<Tabs>
  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments filterCommentsOnDom={true} />
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableFilterCommentsOnDom();
    commentElement.disableFilterCommentsOnDom();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using Props:**

    ```html theme={null}
    <velt-comments filter-comments-on-dom="true"></velt-comments>
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableFilterCommentsOnDom();
    commentElement.disableFilterCommentsOnDom();
    ```
  </Tab>
</Tabs>

#### focusPageModeComposer

Focus the page mode composer input field programmatically.

Use this to direct user attention to the page mode composer.

API Method: \[`focusPageModeComposer()`]\(/api-reference/sdk/api/api-methods#focuspagemode composer)

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Using Hook
    const commentElement = useCommentUtils();
    commentElement.focusPageModeComposer();

    // Using API Method
    const commentElement = client.getCommentElement();
    commentElement.focusPageModeComposer();

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.focusPageModeComposer();
    ```
  </Tab>
</Tabs>

#### onSidebarButtonOnCommentDialogClick

Use this to act on clicks on the Sidebar Button at the bottom of the Comment Dialog.

<img src="https://mintlify.s3.us-west-1.amazonaws.com/velt/async-collaboration/comments/images/customization/onSidebarOnCommentDialogClick.png" alt="" />

<Tabs>
  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments
      onSidebarButtonOnCommentDialogClick={(event) => yourMethod(event)}
    />
    ```

    **Using Hooks:**

    ```jsx theme={null}
    const commentDialogSidebarClickEvent = useCommentDialogSidebarClickHandler();
    useEffect(() => {
      console.log("CommentDialog Sidebar button clicked");
    }, [commentDialogSidebarClickEvent]);
    ```

    **Using API methods:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    let subscription = commentElement
      .onSidebarButtonOnCommentDialogClick()
      .subscribe((event) => yourMethod(event));
    ```

    To unsubscribe from the subscription:

    ```jsx theme={null}
    subscription?.unsubscribe();
    ```
  </Tab>

  <Tab title="HTML">
    **Using Props:**

    ```jsx theme={null}
    <velt-comments onsidebarbuttononcommentdialogclick="yourMethod(event)"></velt-comments>
    ```

    **Using API Methods:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    let subscription = commentElement
      .onSidebarButtonOnCommentDialogClick()
      .subscribe((event) => yourMethod(event));
    ```

    To unsubscribe from the subscription:

    ```jsx theme={null}
    subscription?.unsubscribe();
    ```
  </Tab>
</Tabs>

#### onSignIn

When the user clicks on the sign in button, we will emit an `onSignIn` event that you can handle with your own sign in method.

No data is passed with the event.

<Tabs>
  <Tab title="React / Next.js">
    ```js theme={null}
    <VeltComments onSignIn={() => yourSignInMethod()} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const veltCommentsTag = document.querySelector('velt-comments');

    veltCommentsTag?.addEventListener('onSignIn', (event) => {
    console.log('**_ onCommentSignIn _**');
    console.log(event.detail);
    });

    ```
  </Tab>
</Tabs>

#### showCommentsOnDom

Whether comments are shown on the DOM.

`Default: true`

By default, all the comments will be visible on DOM whenever we are able to detect to elements for that. But users can hide it from DOM if required.

There are 2 ways to show/hide comments on DOM:

Configuring attributes on the React Component:

<Tabs>
  <Tab title="React / Next.js">
    ```js theme={null}
    {/* `true` to show comments, `false` to hide comments */}
    <VeltComments commentsOnDom={false} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    <!-- `true` to show comments, `false` to hide comments -->
    <velt-comments comments-on-dom="false"></velt-comments>
    ```
  </Tab>
</Tabs>

Using API methods:

<Tabs>
  <Tab title="React / Next.js">
    ```js theme={null}
    const commentElement = client.getCommentElement();
    // to show comments on DOM
    commentElement.showCommentsOnDom();
    // to hide comments on DOM
    commentElement.hideCommentsOnDom();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    // to show comments on DOM
    commentElement.showCommentsOnDom();
    // to hide comments on DOM
    commentElement.hideCommentsOnDom();
    ```
  </Tab>
</Tabs>

#### showResolvedCommentsOnDom

Whether to show resolved comments on the DOM.

`Default: false`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments resolvedCommentsOnDom={true} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comments resolved-comments-on-dom="true"></velt-comments>
    ```
  </Tab>
</Tabs>

API Methods:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    // To show resolved comments on dom
    commentElement.showResolvedCommentsOnDom();
    // To hide resolved comments on dom
    commentElement.hideResolvedCommentsOnDom();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    // To show resolved comments on dom
    commentElement.showResolvedCommentsOnDom();
    // To hide resolved comments on dom
    commentElement.hideResolvedCommentsOnDom();
    ```
  </Tab>
</Tabs>

#### updateCommentDialogPosition

* Sometimes when you manually set the position of the Comment Pin, the Comment Dialog might not position itself near the pin in certain scenarios like scrolling, zooming the page when the comment dialog is open.
* Use this to manually trigger an update. The dialog will reposition itself near the pin.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.updateCommentDialogPosition();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.updateCommentDialogPosition();
    ```
  </Tab>
</Tabs>

You can add custom lists at two levels: a. on the CommentAnnotation and b. on the Comment.

#### Link Callback

Enable a callback when users click on links rendered in comment content. When enabled, links won’t automatically open; instead an event is emitted.

How to use:

* By default `linkCallback` is `false`.
* When `false`, clicking a link opens it directly and no callback is triggered.
* When `true`, clicking a link does not open it; instead a `linkClicked` event is emitted so you can handle navigation.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Using Props
    <VeltComments linkCallback={true} />

    // Using Hooks
    const linkEvent = useCommentEventCallback('linkClicked')
    useEffect(() => {
    if (linkEvent) {
    console.log('linkClicked', linkEvent);
    }
    }, [linkEvent]);

    // Using API
    const commentElement = client.getCommentElement();
    commentElement.on('linkClicked').subscribe((linkData) => {
    console.log('linkClicked', linkData);
    });

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comments link-callback="true"></velt-comments>

    <script>
      const commentElement = Velt.getCommentElement();
      commentElement.on('linkClicked').subscribe((linkData) => {
        console.log('Comment link clicked:', linkData);
      });
    </script>
    ```
  </Tab>
</Tabs>

Types:

```ts theme={null}
export interface LinkClickedEvent {
  text: string;
  link: string;
  commentAnnotation: CommentAnnotation;
  commentId: Number;
  metadata?: VeltEventMetadata;
}
```

#### commentBubbleClicked

Listen to when a comment bubble is clicked.

This event is triggered whenever a user clicks on a comment bubble. You can use this to implement custom actions like navigation or analytics tracking.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Using Hook
    const commentBubbleClickedEvent = useCommentEventCallback('commentBubbleClicked');
    useEffect(() => {
      if (commentBubbleClickedEvent) {
        console.log('Comment bubble clicked:', commentBubbleClickedEvent);
      }
    }, [commentBubbleClickedEvent]);

    // Using API
    const commentElement = client.getCommentElement();
    commentElement.on('commentBubbleClicked').subscribe((eventData) => {
    console.log('Comment bubble clicked:', eventData);
    });

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <script>
      const commentElement = Velt.getCommentElement();
      commentElement.on('commentBubbleClicked').subscribe((eventData) => {
        console.log('Comment bubble clicked:', eventData);
      });
    </script>
    ```
  </Tab>
</Tabs>

**Event Type**: [`CommentBubbleClickedEvent`](/api-reference/sdk/models/data-models#commentbubbleclickedevent)

```ts theme={null}
export interface CommentBubbleClickedEvent {
  annotationId: string;
  commentAnnotation: CommentAnnotation;
  metadata?: VeltEventMetadata;
}
```

# Extra Information

#### enableCommentIndex

<img src="https://mintcdn.com/velt/vGgIoGfoceFP8dEI/images/index-indicator.png?fit=max&auto=format&n=vGgIoGfoceFP8dEI&q=85&s=cba1ca1d96d4f9447e5cc32fb62d4865" alt="" width="1280" height="720" data-path="images/index-indicator.png" />

Whether comment index is enabled.

`Default: false`

This appears in the comment sidebar and on the comment pins. When this is on, we show a small icon indicating the comment index in the order of creation date. This enables users to find and navigate to the desired comment quickly.

<Tabs>
  <Tab title="React / Next.js">
    ```js theme={null}
    <VeltComments commentIndex={true} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    <velt-comments comment-index="true"></velt-comments>
    ```
  </Tab>
</Tabs>

API Method:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableCommentIndex();
    commentElement.disableCommentIndex();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableCommentIndex();
    commentElement.disableCommentIndex();
    ```
  </Tab>
</Tabs>

#### enableDeviceInfo

<img src="https://mintcdn.com/velt/kAkMSIYF4ZlrlwLm/images/device-info.png?fit=max&auto=format&n=kAkMSIYF4ZlrlwLm&q=85&s=4e5f88e1f638a5c7d3cbec7dcc88fe79" alt="" width="1280" height="720" data-path="images/device-info.png" />

Whether device type indicator is enabled.

`Default: false`

When this is on, we show additional information in the `Comment Thread` indicating which device the comment was created on. This is useful especially for design tools, where additional context is needed for debugging issues.

<Tabs>
  <Tab title="React / Next.js">
    ```js theme={null}
    <VeltComments deviceInfo={true} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    <velt-comments device-info="true"></velt-comments>
    ```
  </Tab>
</Tabs>

API Method:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableDeviceInfo();
    commentElement.disableDeviceInfo();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableDeviceInfo();
    commentElement.disableDeviceInfo();
    ```
  </Tab>
</Tabs>

#### enableDeviceIndicatorOnCommentPins

<img src="https://mintcdn.com/velt/kAkMSIYF4ZlrlwLm/images/device-info-pin.png?fit=max&auto=format&n=kAkMSIYF4ZlrlwLm&q=85&s=3255d9d2d06a01169e144a9e91f00d69" alt="" width="1280" height="720" data-path="images/device-info-pin.png" />

Whether the device type indicator on `Comment Pins` is enabled.

`Default: false`

When this is on, we show a small device type icon on the `Comment Pin` indicating which device the comment was created on. This is useful especially for design tools, where additional context is needed for debugging issues.

<Tabs>
  <Tab title="React / Next.js">
    ```js theme={null}
    <VeltComments deviceIndicatorOnCommentPins={true} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    <velt-comments device-indicator-on-comment-pins="true"></velt-comments>
    ```
  </Tab>
</Tabs>

API Method:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableDeviceIndicatorOnCommentPins();
    commentElement.disableDeviceIndicatorOnCommentPins();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableDeviceIndicatorOnCommentPins();
    commentElement.disableDeviceIndicatorOnCommentPins();
    ```
  </Tab>
</Tabs>

#### enableGhostComments

<img src="https://mintcdn.com/velt/vGgIoGfoceFP8dEI/images/ghost-comment-pin.png?fit=max&auto=format&n=vGgIoGfoceFP8dEI&q=85&s=73b8c5e9d95200a26e589e5551abc5f3" alt="" width="1280" height="720" data-path="images/ghost-comment-pin.png" />

<img src="https://mintcdn.com/velt/kAkMSIYF4ZlrlwLm/images/ghost-comment-dialog-box.png?fit=max&auto=format&n=kAkMSIYF4ZlrlwLm&q=85&s=8b52e18e25089c38469ec6974571c095" alt="" width="1280" height="720" data-path="images/ghost-comment-dialog-box.png" />

Whether to show ghost comments on the DOM.

`Default: false`

Ghost comments are comments that were once linked to certain content on the DOM but that content is no longer available. If this is on, we display ghost comments in gray, close to where they were originally positioned on the DOM.

<Tabs>
  <Tab title="React / Next.js">
    ```js theme={null}
    <VeltComments ghostComments={true} />
    ```

    **Using API methods:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableGhostComments();
    commentElement.disableGhostComments();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    <velt-comments ghost-comments="true"></velt-comments>
    ```

    **Using API methods:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableGhostComments();
    commentElement.disableGhostComments();
    ```
  </Tab>
</Tabs>

#### enableGhostCommentsIndicator

<img src="https://mintcdn.com/velt/vGgIoGfoceFP8dEI/images/ghost-comment-sidebar.png?fit=max&auto=format&n=vGgIoGfoceFP8dEI&q=85&s=678c427b727079b54ec81d2e9efbf313" alt="" width="1280" height="720" data-path="images/ghost-comment-sidebar.png" />

Whether to show ghost comment labels in the comment sidebar.

`Default: true`

Ghost comments are always shown in the comments sidebar so that users can see the history of all comments. If this is on, we show a label on the comment in the sidebar indicating that the original content on which this comment was added is no longer available. This sets better expectations with the users.

<Tabs>
  <Tab title="React / Next.js">
    ```js theme={null}
    <VeltComments ghostCommentsIndicator={true} />
    ```

    **Using API methods:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableGhostCommentsIndicator();
    commentElement.disableGhostCommentsIndicator();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comments ghost-comments-indicator="true"></velt-comments>
    ```

    **Using API methods:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableGhostCommentsIndicator();
    commentElement.disableGhostCommentsIndicator();
    ```
  </Tab>
</Tabs>

# Special File Type Support

#### Iframe Container Support

<img src="https://mintcdn.com/velt/vGgIoGfoceFP8dEI/images/iframe-comment.png?fit=max&auto=format&n=vGgIoGfoceFP8dEI&q=85&s=83f6a57f334da3de4c6e0aedc4e1489e" alt="" width="1280" height="720" data-path="images/iframe-comment.png" />

* To enable comments on an iframe, add `data-velt-iframe-container="true"` to the iframe's container element.
* Note this will not insert the comments inside the contents of the iframe, but rather on top of the iframe.

```html theme={null}
<div data-velt-iframe-container="true">
  <iframe
    src="https://www.wikipedia.org/"
    width="500px"
    height="500px"
  ></iframe>
</div>
```

#### data-velt-pdf-viewer

<img src="https://mintcdn.com/velt/vGgIoGfoceFP8dEI/images/pdf-comments.png?fit=max&auto=format&n=vGgIoGfoceFP8dEI&q=85&s=47c78b07508421cac669cecfaa1c6100" alt="" width="1280" height="720" data-path="images/pdf-comments.png" />

To support comments on top of a pdf viewer, add the `data-velt-pdf-viewer="true"` attribute in the container element of the pdf viewer.

```html theme={null}
<!-- Add this attribute to the container of your pdf viewer -->
<div id="viewerContainer" data-velt-pdf-viewer="true">
  <!-- Your pdf viewer here -->
  <div id="viewer" class="pdfViewer"></div>
</div>
```

#### svgAsImg

* By default, Velt SDK treats SVGs as layered elements.
* If you want to treat SVGs as flat images, you can use this.
* Default: `false`

<Tabs>
  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments svgAsImg={true} />
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableSvgAsImg();
    commentElement.disableSvgAsImg();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using Props:**

    ```html theme={null}
    <velt-comments svg-as-img="true"></velt-comments>
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableSvgAsImg();
    commentElement.disableSvgAsImg();
    ```
  </Tab>
</Tabs>

# Keyboard Controls

#### enableHotkey

Whether Hotkeys are enabled or not. For now, the only hotkey supported is pressing `c` to enable `comment mode`.

`Default: false`

<Tabs>
  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments hotkey={false} />
    ```

    **Using API Method:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableHotkey();
    commentElement.disableHotkey();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using Props:**

    ```html theme={null}
    <velt-comments hotkey="true"></velt-comments>
    ```

    **Using API Method:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableHotkey();
    commentElement.disableHotkey();
    ```
  </Tab>
</Tabs>

#### enableEnterKeyToSubmit

* By default, pressing `enter` will add a new line and pressing `shift` + `enter` will submit a comment.
* You can change this default behavior so that pressing `enter` will submit a comment by setting the `enterKeyToSubmit` property to `true`.

<Tabs>
  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments enterKeyToSubmit={true} />
    ```

    **Using API Method:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableEnterKeyToSubmit();
    commentElement.disableEnterKeyToSubmit();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using Props:**

    ```jsx theme={null}
    <velt-comments enter-key-to-submit="true"></velt-comments>
    ```

    **Using API Method:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableEnterKeyToSubmit();
    commentElement.disableEnterKeyToSubmit();
    ```
  </Tab>
</Tabs>

#### enableDeleteOnBackspace

* Use this to enable or disable deleting comments when backpsace key is pressed.

Default: `enabled`

<Tabs>
  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments deleteOnBackspace={false} />
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableDeleteOnBackspace();
    commentElement.disableDeleteOnBackspace();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using Props:**

    ```jsx theme={null}
    <velt-comments delete-on-backspace="false"></velt-comments>
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableDeleteOnBackspace();
    commentElement.disableDeleteOnBackspace();
    ```
  </Tab>
</Tabs>

# Moderation

#### enableModeratorMode

<img src="https://mintcdn.com/velt/vGgIoGfoceFP8dEI/images/moderator-mode.png?fit=max&auto=format&n=vGgIoGfoceFP8dEI&q=85&s=1cc209fbf53680874324c4c5679d5d8a" alt="" width="1280" height="720" data-path="images/moderator-mode.png" />

Whether comments require moderator approval.

`Default: false`

By default, when a user adds a comment it is visible to all authenticated users on the same `document`. Moderator mode makes visibility of all comments private to only `admin` users and the comment author. Admin users will see an approve button on the comment dialog. Once approved the comment will be visible to all users who can access the `document`.

You can set some users as `admin` by setting the `isAdmin` property in the User object, during the `identify()` call.

<Tabs>
  <Tab title="React / Next.js">
    ```js theme={null}
    <VeltComments moderatorMode={true} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    <velt-comments moderator-mode="true"></velt-comments>
    ```
  </Tab>
</Tabs>

API Method:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableModeratorMode();
    commentElement.disableModeratorMode();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableModeratorMode();
    commentElement.disableModeratorMode();
    ```
  </Tab>
</Tabs>

#### enableResolveStatusAccessAdminOnly

* Restrict the resolve action to admin users and the comment author only.

<Tabs>
  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments resolveStatusAccessAdminOnly={true} />
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    // To enable resolve status access admin only
    commentElement.enableResolveStatusAccessAdminOnly();
    // To disable resolve status access admin only
    commentElement.disableResolveStatusAccessAdminOnly();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using Props:**

    ```html theme={null}
    <velt-comments resolve-status-access-admin-only="true"></velt-comments>
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    // To enable resolve status access admin only
    commentElement.enableResolveStatusAccessAdminOnly();
    // To disable resolve status access admin only
    commentElement.disableResolveStatusAccessAdminOnly();
    ```
  </Tab>
</Tabs>

#### approveCommentAnnotation

* Approves a comment annotation in moderator mode
* Params: [ApproveCommentAnnotationRequest](/api-reference/sdk/models/data-models#approvecommentannotationrequest)
* Returns: [ApproveCommentAnnotationEvent](/api-reference/sdk/models/data-models#approvecommentannotationevent)

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const approveCommentAnnotationRequest = {
      annotationId: 'ANNOTATION_ID'
    };

    // Hook
    const { approveCommentAnnotation } = useApproveCommentAnnotation();
    const approveCommentAnnotationEvent = await approveCommentAnnotation(approveCommentAnnotationRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const approveCommentAnnotationEvent = await commentElement.approveCommentAnnotation(approveCommentAnnotationRequest);

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const approveCommentAnnotationRequest = {
      annotationId: 'ANNOTATION_ID'
    };

    const commentElement = Velt.getCommentElement();
    const approveCommentAnnotationEvent = await commentElement.approveCommentAnnotation(approveCommentAnnotationRequest);
    ```
  </Tab>
</Tabs>

#### acceptCommentAnnotation

* Accepts a comment annotation in suggestion mode
* Params: [AcceptCommentAnnotationRequest](/api-reference/sdk/models/data-models#acceptcommentannotationrequest)
* Returns: [AcceptCommentAnnotationEvent](/api-reference/sdk/models/data-models#acceptcommentannotationevent)

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const acceptCommentAnnotationRequest = {
      annotationId: 'ANNOTATION_ID'
    };

    // Hook
    const { acceptCommentAnnotation } = useAcceptCommentAnnotation();
    const acceptCommentAnnotationEventData = await acceptCommentAnnotation(acceptCommentAnnotationRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const acceptCommentAnnotationEventData = await commentElement.acceptCommentAnnotation(acceptCommentAnnotationRequest);

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const acceptCommentAnnotationRequest = {
      annotationId: 'ANNOTATION_ID'
    };

    const commentElement = Velt.getCommentElement();
    const acceptCommentAnnotationEventData = await commentElement.acceptCommentAnnotation(acceptCommentAnnotationRequest);
    ```
  </Tab>
</Tabs>

#### rejectCommentAnnotation

* Rejects a comment annotation in suggestion mode
* Params: [RejectCommentAnnotationRequest](/api-reference/sdk/models/data-models#rejectcommentannotationrequest)
* Returns: [RejectCommentAnnotationEvent](/api-reference/sdk/models/data-models#rejectcommentannotationevent)

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const rejectCommentAnnotationRequest = {
      annotationId: 'ANNOTATION_ID'
    };

    // Hook
    const { rejectCommentAnnotation } = useRejectCommentAnnotation();
    const rejectCommentAnnotationEventData = await rejectCommentAnnotation(rejectCommentAnnotationRequest);

    // API Method
    const commentElement = client.getCommentElement();
    const rejectCommentAnnotationEventData = await commentElement.rejectCommentAnnotation(rejectCommentAnnotationRequest);

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    const rejectCommentAnnotationRequest = {
      annotationId: 'ANNOTATION_ID'
    };

    const commentElement = Velt.getCommentElement();
    const rejectCommentAnnotationEventData = await commentElement.rejectCommentAnnotation(rejectCommentAnnotationRequest);
    ```
  </Tab>
</Tabs>

#### enableSuggestionMode

<img src="https://mintcdn.com/velt/gAz_vLsG-ukKamYM/images/accept-reject.png?fit=max&auto=format&n=gAz_vLsG-ukKamYM&q=85&s=83fbf205b67c4e9f7635e72ccd2d8c33" alt="" width="1280" height="720" data-path="images/accept-reject.png" />

Whether to enable suggestion mode to accept or reject comments.

`Default: false`

<Tabs>
  <Tab title="React / Next.js">
    To accept comments, set the `suggestionMode` attribute to `true`.

    ```js theme={null}
    <VeltComments suggestionMode={true} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    To accept comments, set the `suggestion-mode` attribute to `true`.

    ```html theme={null}
    <velt-comments suggestion-mode="true"></velt-comments>
    ```
  </Tab>
</Tabs>

API Method:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableSuggestionMode();
    commentElement.disableSuggestionMode();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableSuggestionMode();
    commentElement.disableSuggestionMode();
    ```
  </Tab>
</Tabs>

#### enableReadOnly

Control whether comments are in read-only mode. When enabled, any features requiring user interaction (e.g., Composer, Reactions, Status) will be removed.

Default: `false`

<Tabs>
  <Tab title="React / Next.JS">
    Using Props:

    ```jsx theme={null}
    <VeltComments readOnly={true} />
    ```

    Using API:

    ```js theme={null}
      const commentElement = client.getCommentElement();
      commentElement.enableReadOnly();
      commentElement.disableReadOnly();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    Using Props:

    ```html theme={null}
    <velt-comments read-only="true"></velt-comments>
    ```

    Using API:

    ```js theme={null}
      const commentElement = Velt.getCommentElement();
      commentElement.enableReadOnly();
      commentElement.disableReadOnly();
    ```
  </Tab>
</Tabs>

# Comment Read Status

#### enableSeenByUsers

Control whether the "Seen By" feature is enabled for comments. When enabled, it shows which users have seen each comment.

Default: `true`

<Tabs>
  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments seenByUsers={false} />
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableSeenByUsers();
    commentElement.disableSeenByUsers();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using Props:**

    ```html theme={null}
    <velt-comments seen-by-users="false"></velt-comments>
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableSeenByUsers();
    commentElement.disableSeenByUsers();
    ```
  </Tab>
</Tabs>

#### setUnreadIndicatorMode

Whether `verbose` mode is enabled for unread `Comments`.

`Default: 'minimal'`

Unread `Comments` can be in `minimal` mode or `verbose` mode.

In `minimal` mode, a small red dot indicator appears for unread `Comments`.

In `verbose` mode, a larger badge with the text "UNREAD" will appear for unread `Comments`.

<Frame>
  <img src="https://mintcdn.com/velt/gY7ilEx2g4g3-HVe/images/unread-compare.png?fit=max&auto=format&n=gY7ilEx2g4g3-HVe&q=85&s=205adde0a88a97a0ffdb82c06c174a78" alt="" width="1280" height="720" data-path="images/unread-compare.png" />
</Frame>

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments unreadIndicatorMode={"verbose"} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    <velt-comments unread-indicator-mode="verbose"></velt-comments>
    ```
  </Tab>
</Tabs>

API Method:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.setUnreadIndicatorMode("verbose"); // use badge with text UNREAD
    commentElement.setUnreadIndicatorMode("minimal"); // use small red dot indicator
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.setUnreadIndicatorMode("verbose"); // use badge with text UNREAD
    commentElement.setUnreadIndicatorMode("minimal"); // use small red dot indicator
    ```
  </Tab>
</Tabs>

# Toggle Comment Types

#### enableAreaComment

Area comments allows users to draw a rectangle and attach a comment to it.
Use this to enable or disable area comments.

Default: `true`

<img src="https://mintcdn.com/velt/kAkMSIYF4ZlrlwLm/images/enable-disable-area-comments.png?fit=max&auto=format&n=kAkMSIYF4ZlrlwLm&q=85&s=3cced9a9ff910f884dc76c6960374ae2" alt="" width="2560" height="1440" data-path="images/enable-disable-area-comments.png" />

<Tabs>
  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments areaComment={false} />
    ```

    **Using API Method:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableAreaComment();
    commentElement.disableAreaComment();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using Props:**

    ```jsx theme={null}
    <velt-comments area-comment="false"></velt-comments>
    ```

    Using API Method:

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableAreaComment();
    commentElement.disableAreaComment();
    ```
  </Tab>
</Tabs>

#### enablePopoverMode

<Info>
  For a complete setup guide for Popover mode, [read
  here](/async-collaboration/comments/setup/popover).
</Info>

Whether Popover Mode is enabled.

Default: `false`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments popoverMode={true}/>
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enablePopoverMode();
    commentElement.disablePopoverMode();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    <velt-comments popover-mode="true"></velt-comments> 
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enablePopoverMode();
    commentElement.disablePopoverMode();
    ```
  </Tab>
</Tabs>

#### enableStreamMode

<Info>
  For a complete setup guide for Stream mode, [read
  here](/async-collaboration/comments/setup/stream).
</Info>

Whether Stream Mode is enabled.

Default: `false`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments streamMode={true}/>
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableStreamMode();
    commentElement.disableStreamMode();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using Props:**

    ```html theme={null}
    <velt-comments stream-mode="true"></velt-comments>
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableStreamMode();
    commentElement.disableStreamMode();
    ```
  </Tab>
</Tabs>

#### enableTextMode

<Info>
  For a complete setup guide for Text mode, [read
  here](/async-collaboration/comments/setup/text).
</Info>

Whether Text Mode is enabled.

Default: `true`

<img src="https://mintcdn.com/velt/gY7ilEx2g4g3-HVe/images/text-comment.png?fit=max&auto=format&n=gY7ilEx2g4g3-HVe&q=85&s=e2938519d890a5c020d1da5407c4557c" alt="" width="1280" height="720" data-path="images/text-comment.png" />

<Tabs>
  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments textMode={true}/>
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableTextComments();
    commentElement.disableTextComments();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using Props:**

    ```html theme={null}
    <velt-comments text-mode="true"></velt-comments> 
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableTextComments();
    commentElement.disableTextComments();
    ```
  </Tab>
</Tabs>

#### enableInlineCommentMode

<img src="https://mintcdn.com/velt/gY7ilEx2g4g3-HVe/images/text-comment-opened.png?fit=max&auto=format&n=gY7ilEx2g4g3-HVe&q=85&s=25a5a817cb85532ce33b9bf08f89d4e5" alt="" width="1024" height="576" data-path="images/text-comment-opened.png" />

Whether In-line comment mode is enabled.

When In-line comment mode is enabled, comments will appear under the text they are associated with in the DOM, instead of as a pop up window.

Default: `false`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments inlineCommentMode={true}/>
    ```

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableInlineCommentMode();
    commentElement.disableInlineCommentMode();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    <velt-comments inline-comment-mode="true"></velt-comments> 
    ```

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableInlineCommentMode();
    commentElement.disableInlineCommentMode();
    ```
  </Tab>
</Tabs>

#### enableMultithread

* By default comments are single threaded.
* You can make it multithreaded by setting `multiThread` prop to `true`.
* If you had previously used a wireframe for the comment dialog, you will need to add the [multithread wireframe](/ui-customization/features/async/comments/multithread-comment-dialog).
* Default: `false`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments multiThread={true} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comments multi-thread="true"></velt-comments>
    ```
  </Tab>
</Tabs>

# Comment Tool

#### context

* Add `context` to the `Velt Comment Tool` component to associate custom metadata with comments created using that tool.
* Predefine context directly within the component itself.
* Currently, this feature is specific to popover comments. This allows you to, for example, assign unique context to each cell in a table if you place a `Velt Comment Tool` in each cell.
* The `context` prop accepts an object with key-value pairs.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // For popover comments
    <VeltCommentTool context={{ key1: 'value1' }} />
    ```
  </Tab>

  <Tab title="HTML">
    ```html theme={null}
    <!-- For popover comments. Make sure to stringify the context object. -->
    <velt-comment-tool context='{"key1": "value1"}'></velt-comment-tool>
    ```
  </Tab>
</Tabs>

#### contextInPageModeComposer

Pass context data to the page mode composer when opening the comment sidebar via the comment tool. Context automatically clears when the sidebar closes.

API Methods: [`enableContextInPageModeComposer()`](/api-reference/sdk/api/api-methods#enablecontextinpagemodecomposer), [`disableContextInPageModeComposer()`](/api-reference/sdk/api/api-methods#disablecontextinpagemodecomposer)

* Params: `boolean`
* Returns: `void`

<Note>
  For programmatically setting context data, see
  [`setContextInPageModeComposer()`](#setcontextinpagemodecomposer).
</Note>

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    // Using props
    import { VeltCommentTool } from '@veltdev/react';

    <VeltCommentTool
      contextInPageModeComposer={true}
      context={{ section: "header", elementId: "nav-menu" }}
    />

    // Using API methods
    const commentElement = client.getCommentElement();
    commentElement.enableContextInPageModeComposer();
    commentElement.disableContextInPageModeComposer();

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comment-tool
      context-in-page-mode-composer="true"
      context='{"section": "header", "elementId": "nav-menu"}'>
    </velt-comment-tool>

    <script>
    const commentElement = Velt.getCommentElement();
    commentElement.enableContextInPageModeComposer();
    commentElement.disableContextInPageModeComposer();
    </script>
    ```
  </Tab>
</Tabs>

#### enableCommentMode

<img src="https://mintcdn.com/velt/2O8vk8YlVD4Kq-ni/images/comment-mode-on-off.png?fit=max&auto=format&n=2O8vk8YlVD4Kq-ni&q=85&s=091c57331bfdf262d0366cef8269a005" alt="" width="1280" height="720" data-path="images/comment-mode-on-off.png" />

Turns Comment mode on or off.

When you click on the comment tool, it turns on comment mode and user can attach comment to any element on the DOM. Using this method you can programmatically turn on the commenting mode.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableCommentMode();
    commentElement.disableCommentMode();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableCommentMode();
    commentElement.disableCommentMode();
    ```
  </Tab>
</Tabs>

#### onCommentModeChange

<img src="https://mintcdn.com/velt/vGgIoGfoceFP8dEI/images/onCommentModeChange.png?fit=max&auto=format&n=vGgIoGfoceFP8dEI&q=85&s=8cbe4996ca371931b658c3270a0e1e28" alt="" width="1280" height="720" data-path="images/onCommentModeChange.png" />

The comment mode is toggled on and off when you click on the Comment Tool.

<Tabs>
  <Tab title="React / Next.js with Hooks">
    The `useCommentModeState()` hook can be used to get the Comment mode without having to subscribe to changes. When the Comment mode changes, the hook return value will update.

    The subscription is automatically unsubscribed when the component dismounts.

    ```jsx theme={null}
    import { useCommentModeState } from "@veltdev/react";

    export default function YourDocument() {
      let commentModeState = useCommentModeState();

      return <div>Comment Mode is turned on: {commentModeState}</div>;
    }
    ```
  </Tab>

  <Tab title="React / Next.js">
    To subscribe to changes in the comment mode, use the `onCommentModeChange()` method , as a property on `VeltCommentTool`:

    ```jsx theme={null}
    <VeltCommentTool onCommentModeChange={(mode) => onCommentModeChange(mode)} />
    ```

    API method:

    ```jsx theme={null}
    let subscription = commentElement.onCommentModeChange().subscribe((mode) => {
      //mode contains the state after change
    });
    ```

    To unsubscribe from the subscription:

    ```jsx theme={null}
    subscription?.unsubscribe();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    API method:

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    let subscription = commentElement.onCommentModeChange().subscribe((mode) => {
        //mode contains the state after change
    });
    ```

    To unsubscribe from the subscription:

    ```jsx theme={null}
    subscription?.unsubscribe()
    ```
  </Tab>
</Tabs>

#### enableCommentTool

<img src="https://mintcdn.com/velt/2O8vk8YlVD4Kq-ni/images/comment-disabled.png?fit=max&auto=format&n=2O8vk8YlVD4Kq-ni&q=85&s=b95aa942ee0ed81b09a5ff2339d6c6db" alt="" width="1280" height="720" data-path="images/comment-disabled.png" />

Whether the Comment Tool button is Enabled.

`Default: true`

When the Comment Tool is disabled, it can not be used to leave comments. Other ways to leave comments, such as highlighting text, will also be disabled.

<Tabs>
  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments commentTool={false} />
    ```

    Using API methods:

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableCommentTool();
    commentElement.disableCommentTool();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using Props:**

    ```html theme={null}
    <velt-comments comment-tool="false"></velt-comments>
    ```

    **Using API methods:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableCommentTool();
    commentElement.disableCommentTool();
    ```
  </Tab>
</Tabs>

#### disabled

Disables the comment tool and prevents users from adding new comments.

This is helpful when you want to temporarily or conditionally restrict comment creation while still allowing users to view existing comments.

Default: `false`

<Note>
  This prop disables the specific comment tool instance it is applied to; the
  `disableCommentTool()` API disables all comment tools globally.
</Note>

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltCommentTool disabled={true} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comment-tool disabled="true"></velt-comment-tool>
    ```
  </Tab>
</Tabs>

#### enableChangeDetectionInCommentMode

* By default, DOM Change Detection is disabled in Comment Mode for better performance.
* You can enable it to automatically reposition comment pins when the DOM changes while in Comment Mode.

`Default: false`

<Tabs>
  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments changeDetectionInCommentMode={true} />
    ```

    **Using API Method:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableChangeDetectionInCommentMode();
    commentElement.disableChangeDetectionInCommentMode();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using Props:**

    ```html theme={null}
    <velt-comments change-detection-in-comment-mode="true"></velt-comments>
    ```

    **Using API Method:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableChangeDetectionInCommentMode();
    commentElement.disableChangeDetectionInCommentMode();
    ```
  </Tab>
</Tabs>

#### enablePersistentCommentMode

* When Persistent comment mode is enabled, you can continue leave additional comments after finishing a comment.
* When it is disabled, you will need to reclick the Comment Tool every time when you want to make a comment.

Default: `false`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments persistentCommentMode={true}/>
    ```

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enablePersistentCommentMode();
    commentElement.disablePersistentCommentMode();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comments persistent-comment-mode="true"></velt-comments>
    ```

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enablePersistentCommentMode();
    commentElement.disablePersistentCommentMode();
    ```
  </Tab>
</Tabs>

#### forceCloseAllOnEsc

* When enabled, pressing the ESC key will force close persistent comment mode even if a comment thread is currently active.
* When disabled (default), pressing ESC will only close the active comment thread but keep persistent comment mode enabled.
* This provides more control over the ESC key behavior in persistent comment mode.

Default: `false`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments forceCloseAllOnEsc={true}/>
    ```

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableForceCloseAllOnEsc();
    commentElement.disableForceCloseAllOnEsc();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    <velt-comments force-close-all-on-esc="true"></velt-comments>
    ```

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableForceCloseAllOnEsc();
    commentElement.disableForceCloseAllOnEsc();
    ```
  </Tab>
</Tabs>

#### setPinCursorImage

You can set custom mouse cursor when the comment mode is on.
The custom cursor image must be **32 x 32 pixels**.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments pinCursorImage={BASE64_IMAGE_STRING} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    <velt-comments pin-cursor-image="BASE64_IMAGE_STRING"></velt-comments>
    ```
  </Tab>
</Tabs>

API Methods:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.setPinCursorImage(BASE64_IMAGE_STRING);
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.setPinCursorImage(BASE64_IMAGE_STRING);
    ```
  </Tab>
</Tabs>

# Minimap

#### enableMinimap

<img src="https://mintcdn.com/velt/vGgIoGfoceFP8dEI/images/minimap.png?fit=max&auto=format&n=vGgIoGfoceFP8dEI&q=85&s=cb9c72890744a274fa255ed00db9b7ba" alt="" width="1280" height="720" data-path="images/minimap.png" />

* The minimap shows a bar on the edge of the screen with indicators that show where comments exist.
* Use this to enable/disable the minimap. By default it's disabled.
* It can be positioned `left` or `right`. By default, it's positioned on the right side of the screen.

**Option a. Enable using config:**

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments minimap={true} minimapPosition="left" />
    ```

    **API Method:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableMinimap();
    commentElement.disableMinimap();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    <velt-comments minimap="true" minimap-position="left"></velt-comments>
    ```

    **API Method:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableMinimap();
    commentElement.disableMinimap();
    ```
  </Tab>
</Tabs>

**Option b. Enable using Minimap Component:**
This offers greater flexibility to customize and position the minimap.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <div className="relative-container">
      <VeltCommentsMinimap targetScrollableElementId="scrollableElement" position="left" />
      <div id="scrollableElement">
          {/* scrollable content */}
      </div>
    </div>

    <style>
      .relative-container {
        position: relative;
      }

      #scrollableElement {
        width: 100%;
        height: 200px; /* or any value */
        overflow: auto;
      }
    </style>

    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    <div class="relative-container">
      <velt-comments-minimap target-scrollable-element-id="scrollableElement" position="left"></velt-comments-minimap>
      <div id="scrollableElement">
          <!-- scrollable content -->
      </div>
    </div>

    <style>
      .relative-container {
        position: relative;
      }

      #scrollableElement {
        width: 100%;
        height: 200px; /* or any value */
        overflow: auto;
      }
    </style>
    ```
  </Tab>
</Tabs>

# Inline Comments Section

#### sortBy and sortOrder

* Change the default sorting order of Comments in the Inline Comments Section.

* Params:
  * `sortBy`: The field to sort by. Currently supports `createdAt` and `lastUpdated`. Default: `lastUpdated` for multithread and `createdAt` for single thread.
  * `sortOrder`: The order to sort by. It can be `asc` or `desc`. Default: `desc` for multithread and `asc` for single thread.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltInlineCommentsSection sortBy="createdAt" sortOrder="desc" />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-inline-comments-section
      sort-by="createdAt"
      sort-order="desc"
    ></velt-inline-comments-section>
    ```
  </Tab>
</Tabs>

#### multiThread

* By default [inline comment section](/async-collaboration/comments/setup/inline-comments) is multithreaded.
* You can make it single threaded by setting `multiThread` prop to `false`.
* Default: `true`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltInlineCommentsSection multiThread={false} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-inline-comments-section multi-thread="false"></velt-inline-comments-section>
    ```
  </Tab>
</Tabs>

#### commentPlaceholder, replyPlaceholder, composerPlaceholder

* Customize placeholder text for different input fields in the inline comments section.
* Props:
  * `commentPlaceholder`: Placeholder text for the main comment input field.
  * `replyPlaceholder`: Placeholder text for the reply input field.
  * `composerPlaceholder`: Placeholder text for the composer input field.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltInlineCommentsSection
      commentPlaceholder="ABC Placeholder"
      replyPlaceholder="ABC Reply Placeholder"
      composerPlaceholder="ABC Composer Placeholder"
    />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-inline-comments-section
      comment-placeholder="ABC Placeholder"
      reply-placeholder="ABC Reply Placeholder"
      composer-placeholder="ABC Composer Placeholder"
    ></velt-inline-comments-section>
    ```
  </Tab>
</Tabs>

#### composerPosition

* Change the position of the comment composer in the inline comments section to `top` or `bottom`.
* Default: `bottom`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltInlineCommentsSection composerPosition="top" />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-inline-comments-section composer-position="top"></velt-inline-comments-section>
    ```
  </Tab>
</Tabs>

#### context

* Pass a custom context object to the Inline Comments Section component.
* The provided context will be added to any comments created in the inline comments section, allowing you to associate custom metadata with those comments.
* Additionally, the component will filter and display only the comments that match the provided context object.
* This dual behavior makes it easy to scope comments to specific areas of your application (e.g., specific cells in a table, dashboard widgets, or data segments).

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltInlineCommentsSection
      context={{
        department: "marketing",
        quarter: "Q1",
        category: "paid-ads",
      }}
    />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-inline-comments-section context='{"department": "marketing", "quarter": "Q1", "category": "paid-ads"}'></velt-inline-comments-section>
    ```
  </Tab>
</Tabs>

#### contextOptions

* Configure the matching behavior for the context object when filtering comments.
* By default, comments must fully match all key-value pairs in the provided context.
* Set `partialMatch: true` to enable flexible matching where comments match if they contain all the specified context fields (extra fields in the comment's context are ignored).
* See [`Context` Matching](#context-matching) for detailed explanation and examples.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    {/* Full match (default) - comment must have exact context */}
    <VeltInlineCommentsSection 
      context={{ department: "marketing", quarter: "Q1" }} 
    />

    {/* Partial match - comment matches if it contains these fields */}

    <VeltInlineCommentsSection 
      context={{ department: "marketing" }} 
      contextOptions={{ partialMatch: true }}
    />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <!-- Full match (default) -->
    <velt-inline-comments-section 
      context='{"department": "marketing", "quarter": "Q1"}'>
    </velt-inline-comments-section>

    <!-- Partial match -->

    <velt-inline-comments-section 
      context='{"department": "marketing"}'
      context-options='{"partialMatch": true}'>
    </velt-inline-comments-section>

    ```
  </Tab>
</Tabs>

#### readOnly

Control read-only mode at the component level. When enabled, users can view comments but cannot reply, edit, or add new comments in the Inline Comments Section.

The local component prop takes precedence over global settings when explicitly set.

Default: `false`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltInlineCommentsSection
      targetElementId="my-element"
      readOnly={true}
    />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-inline-comments-section
      target-element-id="my-element"
      read-only="true">
    </velt-inline-comments-section>
    ```
  </Tab>
</Tabs>

# Popover Comments

#### enableDialogOnTargetElementClick

<img src="https://mintcdn.com/velt/gAz_vLsG-ukKamYM/gifs/hover-cell-comment.gif?s=092f6241ef57b96231d6f837b6ab9743" alt="" width="2560" height="1440" data-path="gifs/hover-cell-comment.gif" />

Whether the comment dialog opens when target element is clicked. This is relevant only for Popover mode.

`Default: true`

<Tabs>
  <Tab title="React / Next.js">
    ```js theme={null}
    <VeltComments dialogOnTargetElementClick={true} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    <velt-comments dialog-on-hover="true"></velt-comments>
    ```
  </Tab>
</Tabs>

API Method:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableDialogOnTargetElementClick();
    commentElement.disableDialogOnTargetElementClick();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableDialogOnTargetElementClick();
    commentElement.disableDialogOnTargetElementClick();
    ```
  </Tab>
</Tabs>

#### enablePopoverTriangleComponent

Whether the popover triangle appears when Popover Mode is enabled.

`Default: true`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltComments popoverTriangleComponent={true}/>
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    <velt-comments popover-triangle-component="true"></velt-comments> 
    ```
  </Tab>
</Tabs>

API Method:

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enablePopoverTriangleComponent();
    commentElement.disablePopoverTriangleComponent();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enablePopoverTriangleComponent();
    commentElement.disablePopoverTriangleComponent();
    ```
  </Tab>
</Tabs>

# Comment Bubble

#### annotationId

* The id of the comment annotation to show the comment bubble on.
* The bubble will be rendered only if there is a comment annotation that matches the provided `annotationId` in the current document.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltCommentBubble annotationId="annotation-id-1" />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comment-bubble annotation-id="annotation-id-1"></velt-comment-bubble>
    ```
  </Tab>
</Tabs>

#### targetElementId

* The DOM ID of the element where comment bubble is added.
* This binds the comment bubble to the element with the provided ID.
* The bubble will be rendered only if there is a comment annotation that was added to the element with the provided ID.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltCommentBubble targetElementId="cell-id-1" />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comment-bubble target-element-id="cell-id-1"></velt-comment-bubble>
    ```
  </Tab>
</Tabs>

#### context

* The `context` object to filter which comment annotations to show the comment bubble for.
* The bubble will be rendered only if there is a comment annotation that matches the provided `context` in the current document.
* Works only with `popover` mode comments.
* Perfect for complex tables with filtering and segmentation needs.
* Set flexible comment anchoring and filtering logic at the cell level using key-value pairs.
* **Supports aggregate views:** Eg: comments added in day view can appear in week/month views automatically.
* Context commonly has combined use with [context options](#contextoptions) and the [group matched comments](#groupmatchedcomments) feature.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltCommentTool context={{ 'key1': 'value1', 'key2': 'value2' }} />
    // Full match
    <VeltCommentBubble context={{ 'key1': 'value1', 'key2': 'value2' }} />
    // Partial match
    <VeltCommentBubble context={{ 'key1': 'value1' }} contextOptions={{ partialMatch: true }} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comment-tool context='{"key1": "value1", "key2": "value2"}'></velt-comment-tool>

    <!-- Full match -->
    <velt-comment-bubble context='{"key1": "value1", "key2": "value2"}'></velt-comment-bubble>
    <!-- Partial match -->
    <velt-comment-bubble context='{"key1": "value1"}' context-options='{"partialMatch": true}'></velt-comment-bubble>
    ```
  </Tab>
</Tabs>

#### contextOptions

* Matching behavior for the context object (default: full match, or set `partialMatch: true` for flexible matching).
* **How Partial Match Works:**
  * A comment will match if ALL provided filter criteria exist in the comment's context
  * Extra fields in the comment's context don't prevent matching
  * Missing fields in the comment's context prevent matching
  * Example: Comment has `{ day: "01", week: "01", month: "jan", product: "cheese", location: "zurich" }`
    * Filter `{ day: "01", product: "cheese" }` → ✅ matches (both fields exist in comment)
    * Filter `{ day: "01", category: "dairy" }` → ❌ no match (category doesn't exist in comment)
* **Partial Match Examples:**
  * Comment has `{ day: "01", week: "01", month: "jan", product: "cheese" }`
  * Filter with `{ day: "01", week: "01", month: "jan", product: "cheese" }` → matches (full)
  * Filter with `{ week: "01", month: "jan", product: "cheese" }` → matches (partial)
  * Filter with `{ day: "01", week: "01", month: "jan", product: "cheese", location: "zurich" }` → no match

#### groupMatchedComments

Whether to group multiple comment annotations in Comment Bubble component when multiple annotations match the provided `context` or `targetElementId`.

Default: `false`

<Tabs>
  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments groupMatchedComments={true} />
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableGroupMatchedComments();
    commentElement.disableGroupMatchedComments();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using Props:**

    ```html theme={null}
    <velt-comments group-matched-comments="true"></velt-comments>
    ```

    **Using API:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableGroupMatchedComments();
    commentElement.disableGroupMatchedComments();
    ```
  </Tab>
</Tabs>

#### commentCountType

Whether to show unread or total comment replies count on Comment Bubble Component.

Type: [`CommentCountType`](/api-reference/sdk/models/data-models#commentcounttype)

* `total`: Shows the total number of replies. (default)
* `unread`: Shows the number of unread replies.

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltCommentBubble commentCountType={"unread"} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```jsx theme={null}
    <velt-comment-bubble comment-count-type="unread">
    </velt-comment-bubble>
    ```
  </Tab>
</Tabs>

#### openDialog

Control whether the comment dialog opens when clicking on the comment bubble.

When disabled, clicking the bubble will not open the comment dialog. This is useful when you want to handle bubble clicks with custom logic using the [`commentBubbleClicked`](#commentbubbleclicked) event.

Default: `true`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltCommentBubble openDialog={false} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comment-bubble open-dialog="false"></velt-comment-bubble>
    ```
  </Tab>
</Tabs>

#### readOnly

The `readOnly` flag prevents users from replying or editing existing comments in the target bubble while still displaying them.

This is useful when you want to display comments in a read-only mode where users can view but not modify or respond to comments.

Default: `false`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltCommentBubble readOnly={true} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comment-bubble read-only="true"></velt-comment-bubble>
    ```
  </Tab>
</Tabs>

# Video Timeline Comments

#### setTotalMediaLength

Set the total length of media (in frames or seconds) for the timeline.

<Tabs>
  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltCommentPlayerTimeline totalMediaLength={120} />
    ```

    **Using API Method:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.setTotalMediaLength(120);
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using Props:**

    ```html theme={null}
    <velt-comment-player-timeline total-media-length="120"></velt-comment-player-timeline>
    ```

    **Using API Method:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.setTotalMediaLength(120);
    ```
  </Tab>
</Tabs>

#### offset

* Allows comment bubbles to be positioned relative to both parent and child video clips by specifying an offset value.
* Default: `0`

<Tabs>
  <Tab title="React / Next.js">
    ```jsx theme={null}
    <VeltCommentPlayerTimeline offset={10} />
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```html theme={null}
    <velt-comment-player-timeline offset="10"></velt-comment-player-timeline>
    ```
  </Tab>
</Tabs>

# Comment Pin

#### enableBubbleOnPin

Show a Comment Bubble when user hovers or clicks on the Comment Pin vs showing the Comment Dialog.
The comment dialog will open only on clicking the comment bubble.

`Default: 'false'`

<Tabs>
  <Tab title="React / Next.js with Hooks">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments bubbleOnPin={true} />
    ```

    **Using API Method:**

    ```jsx theme={null}
    const commentElement = useCommentUtils();
    commentElement.enableBubbleOnPin();
    commentElement.disableBubbleOnPin();
    ```
  </Tab>

  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments bubbleOnPin={true} />
    ```

    **Using API Method:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    commentElement.enableBubbleOnPin();
    commentElement.disableBubbleOnPin();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using Props:**

    ```jsx theme={null}
    <velt-comments bubble-on-pin="true">
    </velt-comments>
    ```

    **Using API Method:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    commentElement.enableBubbleOnPin();
    commentElement.disableBubbleOnPin();
    ```
  </Tab>
</Tabs>

#### enableBubbleOnPinHover

Show a Comment Bubble when user hovers on the Comment Pin vs clicks on it.

`Default: 'true'`

<Tabs>
  <Tab title="React / Next.js with Hooks">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments bubbleOnPin={true} bubbleOnPinHover={false} />
    ```

    **Using API Method:**

    ```jsx theme={null}
    const commentElement = useCommentUtils();

    // To enable/disable showing bubble on pin
    commentElement.enableBubbleOnPin();
    commentElement.disableBubbleOnPin();

    // To enable/disable showing bubble on hover
    commentElement.enableBubbleOnPinHover();
    commentElement.disableBubbleOnPinHover();

    ```
  </Tab>

  <Tab title="React / Next.js">
    **Using Props:**

    ```jsx theme={null}
    <VeltComments bubbleOnPin={true} bubbleOnPinHover={false} />
    ```

    **Using API Method:**

    ```jsx theme={null}
    const commentElement = client.getCommentElement();
    // To enable/disable showing bubble on pin
    commentElement.enableBubbleOnPin();
    commentElement.disableBubbleOnPin();

    // To enable/disable showing bubble on hover
    commentElement.enableBubbleOnPinHover();
    commentElement.disableBubbleOnPinHover();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    **Using Props:**

    ```jsx theme={null}
    <velt-comments bubble-on-pin="true" bubble-on-pin-hover="false"></velt-comments>
    ```

    **Using API Method:**

    ```jsx theme={null}
    const commentElement = Velt.getCommentElement();
    // To enable/disable showing bubble on pin
    commentElement.enableBubbleOnPin();
    commentElement.disableBubbleOnPin();

    // To enable/disable showing bubble on hover
    commentElement.enableBubbleOnPinHover();
    commentElement.disableBubbleOnPinHover();

    ```
  </Tab>
</Tabs>

# Legacy Methods

#### onCommentAdd

<Tabs>
  <Tab title="React / Next.js">
    Using Props:

    ```js theme={null}
    <VeltComments onCommentAdd={(event) => yourMethod(event)} />

    const yourMethod = (event) => {
      event?.addContext({ customKey: 'customValue' });
    }
    ```

    Using Hooks:

    ```jsx theme={null}
    import { useCommentAddHandler } from "@veltdev/react";

    export default function YourDocument() {
      const commentAddEvent = useCommentAddHandler();

      useEffect(() => {
        console.log("commentAddEvent", commentAddEvent);
      }, [commentAddEvent]);

      return <div></div>;
    }
    ```

    Using API:

    ```js theme={null}
    const commentElement = client.getCommentElement();

    commentElement.onCommentAdd().subscribe((event) => {
      console.log("commentAddEvent", event);
    });
    ```
  </Tab>

  <Tab title="Other Frameworks">
    Using Event listener:

    ```js theme={null}
    const veltCommentsTag = document.querySelector("velt-comments");

    veltCommentsTag?.addEventListener("onCommentAdd", (event) => {
      console.log("*** onCommentAdd ***");
      console.log(event.detail);
      event.detail?.addContext({ customKey: "customValue" });
    });
    ```

    Using API method:

    ```js theme={null}
    const commentElement = Velt.getCommentElement();

    commentElement.onCommentAdd().subscribe((event) => {
      event?.addContext({ customKey: "customValue" });
    });
    ```
  </Tab>
</Tabs>

**onCommentAdd Event Data Schema**

| Field Name         | Type              | Description                                                         |
| ------------------ | ----------------- | ------------------------------------------------------------------- |
| addContext         | Function          | Use this to set custom data on the comment                          |
| annotation         | CommentAnnotation | The annotation that is associated with the comment that was updated |
| documentId         | string            | The document ID where the comment was added                         |
| location           | Object            | The location where the comment was added                            |
| targetAnnotationId | string            | The id of the target annotation                                     |

#### onCommentUpdate

<Tabs>
  <Tab title="React / Next.js">
    Using Props:

    ```js theme={null}
    <VeltComments onCommentUpdate={(event) => yourMethod(event)} />;

    const yourMethod = (event) => {
      console.log("commentUpdateEvent", event);
    };
    ```

    Using Hooks:

    ```jsx theme={null}
    import { useCommentUpdateHandler } from "@veltdev/react";

    export default function YourDocument() {
      const commentUpdateEvent = useCommentUpdateHandler();
      useEffect(() => {
        console.log("commentUpdateEvent", commentUpdateEvent);
      }, [commentUpdateEvent]);

      return <div></div>;
    }
    ```

    Using API:

    ```js theme={null}
    const commentElement = client.getCommentElement();

    commentElement.onCommentUpdate().subscribe((event) => {
      console.log("commentUpdateEvent", event);
    });
    ```
  </Tab>

  <Tab title="Other Frameworks">
    Using Event Listener:

    ```js theme={null}
    const veltCommentsTag = document.querySelector('velt-comments');

    veltCommentsTag?.addEventListener('onCommentUpdate', (event) => {
    console.log('**_ onCommentUpdate _**');
    console.log(event.detail);
    });

    ```

    Using API method:

    ```js theme={null}
    const commentElement = Velt.getCommentElement();

    commentElement.onCommentUpdate().subscribe((event) => {
      console.log('commentUpdateEvent', event);
    });
    ```
  </Tab>
</Tabs>

**onCommentUpdate Event Data Schema**

| Field Name         | Type              | Description                                                                |
| ------------------ | ----------------- | -------------------------------------------------------------------------- |
| annotation         | CommentAnnotation | The annotation that is associated with the comment that was updated        |
| type               | string            | The type of comment that was updated                                       |
| targetAnnotationId | string            | The ID of the target annotation that contains the comment that was updated |
| targetCommentId    | number            | The ID of the target comment that was updated                              |
| updateContext      | Function          | Use this to update the custom metadata on the comment annotation.          |

#### getAllCommentAnnotations

* Get all comment annotations for a given document and location.
* By default, it will return data for the current `documentId` and `location`.
* Params (optional):
  * `documentId`: string; it will return all comments in the given `documentId`.
  * `location`: Object; it will return all comments in the given `location`.

<Tabs>
  <Tab title="React / Next.js">
    **Using Hooks:**

    ```jsx theme={null}
    const commentAnnotations = useCommentAnnotations();
    useEffect(() => {
      if (commentAnnotations) {
        console.log("commentAnnotations", commentAnnotations);
      }
    }, [commentAnnotations]);
    ```

    **Using API:**

    ```js theme={null}
    const commentElement = client.getCommentElement();
    let subscription = commentElement
      .getAllCommentAnnotations()
      .subscribe((comments) => {
        console.log("commentAnnotations", comments);
      });
    ```

    To unsubscribe from the subscription:

    ```jsx theme={null}
    subscription?.unsubscribe();
    ```
  </Tab>

  <Tab title="Other Frameworks">
    ```js theme={null}
    if (Velt) {
      const commentElement = Velt.getCommentElement();
      let subscription = commentElement.getAllCommentAnnotations().subscribe((comments) => {
        // Do something with comments
      });
    }
    ```

    To unsubscribe from the subscription:

    ```jsx theme={null}
    subscription?.unsubscribe()
    ```
  </Tab>
</Tabs>
