---
title: "PDF annotation tooltip | Nutrient"
canonical_url: "https://www.nutrient.io/guides/web/samples/custom-annotation-tooltip/"
md_url: "https://www.nutrient.io/guides/web/samples/custom-annotation-tooltip.md"
last_updated: "2026-06-08T09:14:14.477Z"
description: "Learn to add custom actions for selected annotations. Explore our guide on enhancing the annotation inspector for improved user experience and functionality."
---

# Customize PDF annotation tooltips using JavaScript

Add a custom tool or action that’s shown when an annotation is selected. Get additional resources by visiting our guide about [customizing the annotation inspector in our viewer](/guides/web/user-interface/annotations/inspector.md).

[Get Started](https://www.nutrient.io/sdk/web/getting-started.md)

[All Samples](https://www.nutrient.io/guides/web/samples.md)

[Download](https://www.nutrient.io/guides/web/downloads.md)

[Launch Demo](https://www.nutrient.io/demo/)

---

```js

import PSPDFKit from "@nutrient-sdk/viewer";

// Keep track of the current instance so that we
// can use it inside the annotation tooltip callback.
let instance = null;

export function load(defaultConfiguration) {
  return PSPDFKit.load({...defaultConfiguration,
    annotationTooltipCallback: duplicateAnnotationTooltipCallback,
  }).then((_instance) => {
    instance = _instance;

    return instance;
  });
}

function duplicateAnnotationTooltipCallback(annotation) {
  // Duplicating does not make sense for a markup annotation
  if (annotation instanceof PSPDFKit.Annotations.MarkupAnnotation) {
    return [];
  }

  // This is the tooltip item that will be used.
  const duplicateItem = {
    type: "custom",
    title: "Duplicate",
    id: "tooltip-duplicate-annotation",
    className: "TooltipItem-Duplication",
    onPress: async () => {
      // For the new annotation, we will copy the current one but
      // translate the annotation for 50px so that our users see the
      // duplicated annotation.
      const offset = 50;
      const offsetTranslation = new PSPDFKit.Geometry.Point({
        x: offset,
        y: offset,
      });

      const newBoundingBox =
        annotation.boundingBox.translate(offsetTranslation);

      // To make duplication work, we also need to remove the ID
      // of the annotation.
      let duplicatedAnnotation = annotation.set("id", null).set("boundingBox", newBoundingBox);

      // When it's an InkAnnotation, we not only need to move the bounding box
      // but also change the coordinates of the line. Since an ink annotation
      // could contain of multiple segments, we need go change each segment.
      // You can read more about the structure of InkAnnotations here:
      // https://www.nutrient.io/api/web/PSPDFKit.Annotations.InkAnnotation.html
      if (duplicatedAnnotation instanceof PSPDFKit.Annotations.InkAnnotation) {
        duplicatedAnnotation = duplicatedAnnotation.set(
          "lines",
          duplicatedAnnotation.lines.map((line) => {
            return line.map((point) => point.translate(offsetTranslation));
          })
        );
      }

      // For some shape annotations, we may not only need to move the bounding box
      // but also change the coordinates of the shape, defined by the `startPoint`
      // and `endPoint` properties for line, and `points` for polyline and
      // polygon annotations, as well as `cloudyBorderInset` for annotations
      // with a cloudy border set.
      // You can read more about the structure of shape annotations here:
      // https://www.nutrient.io/api/web/PSPDFKit.Annotations.LineAnnotation.html
      // https://www.nutrient.io/api/web/PSPDFKit.Annotations.PolylineAnnotation.html
      // https://www.nutrient.io/api/web/PSPDFKit.Annotations.PolygonAnnotation.html
      if (duplicatedAnnotation instanceof PSPDFKit.Annotations.LineAnnotation) {
        duplicatedAnnotation = duplicatedAnnotation.set(
            "startPoint",
            duplicatedAnnotation.startPoint.translate(offsetTranslation)
          ).set(
            "endPoint",
            duplicatedAnnotation.endPoint.translate(offsetTranslation)
          );
      }

      if (
        duplicatedAnnotation instanceof
          PSPDFKit.Annotations.PolygonAnnotation ||
        duplicatedAnnotation instanceof PSPDFKit.Annotations.PolylineAnnotation
      ) {
        duplicatedAnnotation = duplicatedAnnotation.set(
          "points",
          duplicatedAnnotation.points.map((point) =>
            point.translate(offsetTranslation)
          )
        );
      }

      // In the end, we just use `createAnnotation` on our
      // Nutrient Web SDK instance.
      await instance.create(duplicatedAnnotation);
    },
  };

  return [duplicateItem];
}

```

This code sample is an example that illustrates how to use our SDK. Please adapt it to your specific use case.

---

## Related pages

- [Add watermarks to PDFs using JavaScript example](/guides/web/samples/add-watermarks-to-pdf-javascript.md)
- [Customize PDF annotation permissions using JavaScript](/guides/web/samples/custom-annotation-permissions.md)
- [PDF Collaboration permissions using JavaScript](/guides/web/samples/collaboration-permissions.md)
- [Customize the UI for PDF annotations using JavaScript](/guides/web/samples/annotations-inspector.md)
- [JavaScript PDF magazine viewer](/guides/web/samples/javascript-magazine-viewer.md)
- [Add electronic signature images to PDFs using JavaScript](/guides/web/samples/adding-image-electronic-signatures.md)
- [Hide or reveal area on PDFs using JavaScript](/guides/web/samples/hide-reveal-area-in-pdf.md)
- [PDF annotation in JavaScript](/guides/web/samples/javascript-pdf-annotations.md)
- [Redact PDFs using JavaScript](/guides/web/samples/javascript-pdf-redaction.md)
- [Open PDFs using JavaScript](/guides/web/samples/open-pdf-using-javascript.md)
- [PDF presentation mode using JavaScript](/guides/web/samples/presentation-mode.md)
- [View PDFs in dark mode using JavaScript](/guides/web/samples/dark-mode-pdf-viewer.md)
- [Customizing JavaScript PDF printing modes](/guides/web/samples/pdf-printing-modes.md)
- [Customized Document Editor Toolbar](/guides/web/samples/customized-document-editor-toolbar.md)
- [PDF text selection using JavaScript](/guides/web/samples/pdf-text-selection-javascript.md)
- [Drag-and-drop UI in our JavaScript PDF viewer](/guides/web/samples/drag-and-drop.md)
- [Zoom example for our JavaScript PDF viewer](/guides/web/samples/zooming.md)
- [Open, view, and annotate on images using JavaScript](/guides/web/samples/annotating-images.md)
- [Handling password-protected PDFs in our JavaScript viewer](/guides/web/samples/password-protected-pdf.md)
- [Collaborate on PDFs using JavaScript](/guides/web/samples/instant-pdf-collaboration.md)
- [PDF form support using JavaScript](/guides/web/samples/javascript-pdf-form.md)
- [Create custom overlays on PDFs using JavaScript](/guides/web/samples/custom-overlay-items.md)
- [Custom HTML PDF annotations using JavaScript](/guides/web/samples/custom-annotations.md)
- [Add electronic signatures to PDFs using JavaScript](/guides/web/samples/electronic-signatures-in-pdf.md)
- [Customize the PDF toolbar using JavaScript](/guides/web/samples/customized-pdf-toolbar.md)
- [Customizing PDF text search using JavaScript](/guides/web/samples/customized-pdf-search.md)
- [Flipbook PDF viewer using JavaScript](/guides/web/samples/flipbook.md)
- [Disable PDF editing and annotations](/guides/web/samples/open-read-only-pdf.md)
- [Digitally sign a PDF using JavaScript](/guides/web/samples/javascript-digital-signatures.md)
- [Edit PDFs using JavaScript](/guides/web/samples/edit-pdf-javascript.md)
- [Storing electronic signatures in the browser using JavaScript](/guides/web/samples/stored-electronic-signatures.md)

