Extended Set of React components for PDF annotation
npm install @nicklasastorian/react-pdf-annotatorSet of React components for PDF annotation.
> Note: This is a fork of agentcooper/react-pdf-highlighter with significant UX improvements.
- Built on top of PDF.js
- Text and image highlights
- Popover text for highlights
- Scroll to highlights
This fork includes the following enhancements:
rgba(255, 212, 0, 0.4))renderPopup | Simpler alternative to highlightTransform for hover action bars |onTextLayerReady | Callback when a page's text layer is rendered |onDocumentReady | Callback when document is ready |forceRenderOnLoad | Force re-render highlights when all pages loaded |onHighlightHover | Callback when a highlight is hovered |onHighlightBlur | Callback when a highlight loses hover |disallowOverlappingHighlights | Prevent creating overlapping text highlights on the same line |onOverlap | Callback fired when a selection overlaps an existing highlight |``bash`
npm install react-pdf-highlighter
`tsx`
import "react-pdf-highlighter/dist/style.css";
`bash`
npm install
npm start
The example demonstrates:
- Slide-over panel pattern
- Zoom controls (Ctrl+scroll or buttons)
- Morphing toolbar (save → edit)
- Comment dialog modal
- In-memory highlight persistence
`tsx
import { PdfHighlighter, PdfLoader } from "react-pdf-highlighter";
import "react-pdf-highlighter/dist/style.css";
{(pdfDocument) => (
enableAreaSelection={(event) => event.altKey}
onScrollChange={() => {}}
scrollRef={(scrollTo) => { / store scrollTo / }}
onSelectionFinished={(position, content, hideTipAndSelection, transformSelection) => (
saveHighlight({ position, content });
hideTipAndSelection();
}}
/>
)}
renderPopup={(highlight) => (
)}
highlights={highlights}
/>
)}
`
useHighlights is an optional convenience hook for managing highlight state while keeping your data source external (React Query, Redux, etc.).
`tsx
import { useState } from "react";
import { useHighlights } from "react-pdf-highlighter";
const [highlights, setHighlights] = useState
const {
addHighlight,
updateHighlight,
deleteHighlight,
saveComment,
} = useHighlights({
highlights,
setHighlights,
});
`
This pattern lets you merge/split your own persistence models in setHighlights and rehydrate via async fetches.
useZoom provides a small controller for zooming the PDF viewer (buttons + ctrl/cmd + wheel).
`tsx
import { useRef } from "react";
import { useZoom } from "react-pdf-highlighter";
const containerRef = useRef
const { pdfScaleValue, zoomLabel, zoomIn, zoomOut, fitWidth } = useZoom(
containerRef,
true,
);
`
loads a PDFDocumentProxy using PDF.js and hands it to your render prop.
- PdfHighlighter owns a PDF.js PDFViewer, attaches selection/scroll listeners, and renders highlights into a per-page overlay layer.
- Text selections call onSelectionFinished with a ScaledPosition and text content; area selections are handled by MouseSelection and yield image content.
- Highlights are rendered via highlightTransform (custom) or the default transform, which chooses Highlight for text or AreaHighlight for images and can show a popup via renderPopup.$3
- ScaledPosition is stored in PDF/viewport-independent units (optionally usePdfCoordinates).
- Position is viewport pixels used for rendering. scaledToViewport and viewportToScaled live in src/lib/coordinates.ts.
- IHighlight is the base interface for highlight objects; HighlightHooks exposes onCreate, onUpdate, and onDelete.$3
- src/index.ts is the public entry point; it re-exports components, types, and the global CSS.
- src/components/ contains PdfHighlighter, PdfLoader, and the overlay UI (Highlight, AreaHighlight, TipContainer).
- src/lib/ contains PDF.js DOM helpers, coordinate conversions, and geometry utilities.
- src/style/ holds CSS modules plus index.css which imports the PDF.js viewer styles.$3
- Vite builds the package and emits JS + CSS into dist/.
- Types are emitted via vite-plugin-dts and exposed at dist/index.d.ts.
- The published package exposes dist/style.css for styling.API Reference
./example/src/App.tsx for a complete implementation example.API Improvement Ideas (Future)
These are optional, backward-compatible ideas that could simplify usage and improve extensibility:
- Decouple UI from selection: make
onSelectionFinished return data/payload, with an optional renderSelection for UI.
- Consolidate highlight types: collapse HighlightPayload/HighlightBase/IHighlight into a clearer, generic model (typed meta).
- Unified PDF.js options: accept a single pdfjsOptions object (worker/cMap/viewer) to reduce prop surface area.
- Public coordinate helpers: export scaledToViewport/viewportToScaled` from the public API for consumers.MIT