0

PDF Comment Button

A toggle that arms the pin tool so the next click on the page drops a comment.

"use client";

import { createPluginRegistration } from "@embedpdf/core";

About

<PdfCommentButton /> is the entry point to commenting. Pressing it arms the annotation plugin's built-in textComment tool; the next click on a page drops a comment pin. Each pin is a PDF Text annotation, which <PdfCommentLayer /> draws on-page as an avatar marker and <PdfCommentSidebar /> lists as a thread.

  • Reflects the armed tool — the toggle's pressed state tracks whether textComment is the active tool, so it stays in sync when the tool is armed or disarmed from anywhere else.
  • Respects permissions — when the document forbids annotating, the toggle is disabled with a tooltip explaining why, rather than looking armable but doing nothing.

Comment pins are part of the annotation plugin, which is a heavy-tier plugin <PdfViewer /> does not register for you. The plugin and the comment layer both have to be added before this button does anything — both are shown below.

Installation

pnpm dlx shadcn@latest add @pdfviewcn/comment-button

Usage

Register the annotation plugin.

import { createPluginRegistration } from "@embedpdf/core";
import { AnnotationPluginPackage } from "@embedpdf/plugin-annotation/react";
 
// Outside the component — a new array identity on every render tears the
// engine down and rebuilds it. `annotationAuthor` attributes the pins.
const plugins = [
  createPluginRegistration(AnnotationPluginPackage, {
    annotationAuthor: "You",
  }),
];

Render the comment layer and the button.

<PdfViewer
  documents={[{ url: "/sample.pdf" }]}
  plugins={plugins}
  className="h-[720px]"
>
  <PdfToolbar>
    <PdfCommentButton />
  </PdfToolbar>
  <PdfViewerContent
    pageLayers={({ documentId, pageIndex }) => (
      <PdfCommentLayer documentId={documentId} pageIndex={pageIndex} />
    )}
  />
</PdfViewer>

The button arms the tool; the layer is what the click lands on. <PdfCommentLayer /> is the annotation layer with the composer, the avatar pin, and the thread wired in — mount a bare <PdfAnnotationLayer> here instead and the button still works, but a comment draws as the PDF spec's yellow note icon with nothing to open.

Pair it with <PdfCommentSidebar /> to read and reply to the threads the pins create.

Examples

Default

"use client";

import { createPluginRegistration } from "@embedpdf/core";

With a thread on the pin

A pin on its own is a marker. <PdfCommentLayer /> makes it a conversation — an avatar marker that opens its thread when picked, and a composer before the pin is ever written. See PDF Comment for the pieces it wires together.

"use client";

import { createPluginRegistration } from "@embedpdf/core";

Alongside the annotation tools

The button is an ordinary toggle, so it sits in a toolbar run next to <PdfAnnotationToolbar />. Both read the same active-tool state, so arming one disarms the other:

<PdfToolbar>
  <PdfAnnotationToolbar />
  <PdfToolbarSeparator />
  <PdfCommentButton />
</PdfToolbar>

Accessibility

The button is shadcn's <Toggle /> — a real <button> with aria-pressed, reachable with Tab and operable with Enter or Space. It carries aria-label="Comment", matching its tooltip, so the label is available whether or not the tooltip is shown.

Pressed state is read from the plugin's active tool rather than tracked from the click, so arming or disarming the tool anywhere else — a keyboard shortcut, another control — is announced here too.

A document that forbids annotating disables the button rather than hiding it, keeping tab order stable, and the tooltip says why instead of leaving a control that looks armable but does nothing.

API Reference

PdfCommentButton

A <Toggle /> carrying data-slot="pdf-comment-button", bound to the annotation plugin's active tool. Accepts every <Toggle /> prop except pressed and value, which it owns.

Returns null when the document isn't loaded or the annotation plugin isn't registered. It disables itself when the active document forbids modifying annotations. See Permissions for the full model.