Thumbnail Plugin
The Thumbnail Plugin adds a classic sidebar view with small, clickable previews of each page. It’s an intuitive way for users to get an overview of the document and quickly jump to a specific page.
For optimal performance with long documents, the plugin uses virtualization, rendering only the thumbnail images that are currently visible in the sidebar’s viewport.
Installation
This plugin needs the Render plugin to work. The Scroll plugin is optional but required for the auto-scroll feature.
npm install @embedpdf/plugin-thumbnail @embedpdf/plugin-render @embedpdf/plugin-scrollRegistration
Import ThumbnailPluginPackage and its dependencies, then add them to the plugins array. The dependencies should be registered before the thumbnail plugin.
import { createPluginRegistration } from '@embedpdf/core'
import { EmbedPDF } from '@embedpdf/core/react'
// ... other imports
import { RenderPluginPackage } from '@embedpdf/plugin-render/react'
import { ScrollPluginPackage } from '@embedpdf/plugin-scroll/react'
import { ThumbnailPluginPackage } from '@embedpdf/plugin-thumbnail/react'
const plugins = [
// ... other essential plugins
createPluginRegistration(LoaderPluginPackage, { /* ... */ }),
createPluginRegistration(ViewportPluginPackage),
// Register dependencies first
createPluginRegistration(RenderPluginPackage),
createPluginRegistration(ScrollPluginPackage),
// Register and configure the thumbnail plugin
createPluginRegistration(ThumbnailPluginPackage, {
width: 120, // Sets the width of thumbnail images
}),
]Usage
The plugin features two main components: <ThumbnailsPane /> (the virtualized container) and <ThumbImg /> (for rendering the page image).
Building a Thumbnail Sidebar
You’ll typically place <ThumbnailsPane /> in a sidebar next to your main <Viewport />. It uses a render prop pattern, where you provide a function as its child. This function gets called for each visible thumbnail, receiving metadata (m) about its dimensions and position. You then use this metadata to style your thumbnail container, inside of which you’ll render the <ThumbImg meta={m} /> component.
To handle navigation, you can use the useScroll hook to get the scrollToPage function and the currentPage for highlighting the active thumbnail.
Using the meta Object
The meta object passed to your render prop contains pre-calculated values that are crucial for the plugin’s virtualization and scrolling logic to work correctly. Here’s a breakdown of the key properties and how to use them:
m.top: The absolute vertical position of the thumbnail wrapper. You must apply this to your wrapper element’stopstyle.m.wrapperHeight: The total height of the thumbnail’s container, including the image, label, and padding. You must apply this to your wrapper element’sheightstyle.m.width&m.height: The dimensions of the thumbnail image itself. Apply these to the element that contains the<ThumbImg />component.m.labelHeight: The height reserved for the page label.m.padding: The padding around the thumbnail image.
By correctly applying top and wrapperHeight, you ensure that the virtualized layout is rendered without gaps or overlaps.
import { useScroll } from '@embedpdf/plugin-scroll/react';
import { ThumbnailsPane, ThumbImg } from '@embedpdf/plugin-thumbnail/react';
const ThumbnailSidebar = () => {
const { state, provides } = useScroll();
return (
<ThumbnailsPane>
{(m) => {
const isActive = state.currentPage === m.pageIndex + 1;
return (
<div
key={m.pageIndex}
style={{
position: 'absolute',
top: m.top,
height: m.wrapperHeight,
// ... other wrapper styles
}}
onClick={() => provides?.scrollToPage({ pageNumber: m.pageIndex + 1 })}
>
<div
style={{
border: `2px solid ${isActive ? 'blue' : 'grey'}`,
width: m.width,
height: m.height,
}}
>
<ThumbImg meta={m} />
</div>
<span style={{ height: m.labelHeight }}>
{m.pageIndex + 1}
</span>
</div>
);
}}
</ThumbnailsPane>
);
};Live Example
This example shows a complete PDF viewer with a thumbnail sidebar. Clicking a thumbnail will navigate the main document, and the active thumbnail is highlighted with a blue border.
API Reference
Configuration (ThumbnailPluginConfig)
| Option | Type | Description |
|---|---|---|
width | number | The width of the thumbnail image in CSS pixels. Default: 120 |
gap | number | The vertical space between each thumbnail in CSS pixels. Default: 8 |
buffer | number | The number of off-screen thumbnails to render above and below the visible area. Default: 3 |
labelHeight | number | The height reserved for the page number label below the image. Default: 16 |
autoScroll | boolean | If true, the sidebar automatically scrolls to keep the current page’s thumbnail in view. Default: true |
scrollBehavior | string | The scroll animation ('smooth' or 'auto'). Default: 'smooth' |
imagePadding | number | Padding inside the thumbnail’s border, around the image itself. Default: 0 |
paddingY | number | Vertical padding for the top and bottom of the entire thumbnail container. Default: 0 |
Component: <ThumbnailsPane />
The virtualized scroll container for the thumbnails.
| Prop | Type | Description |
|---|---|---|
children | (meta: ThumbMeta) => ReactNode | (Required) A render prop function that receives thumbnail metadata and returns the component for a single thumbnail. |
Component: <ThumbImg />
Renders the rasterized image for a single thumbnail.
| Prop | Type | Description |
|---|---|---|
meta | ThumbMeta | (Required) The metadata object for the thumbnail, provided by the <ThumbnailsPane /> render prop. |
Hook: useThumbnailCapability()
Provides access to the plugin’s methods, though direct interaction is rarely needed due to the autoScroll feature.
Returns
| Property | Type | Description |
|---|---|---|
provides | ThumbnailCapability | null | An object with methods to interact with the plugin, or null if not ready. |
ThumbnailCapability Methods
| Method | Description |
|---|---|
scrollToThumb(pageIndex) | Programmatically scrolls the thumbnail sidebar to make the specified page thumbnail visible. |
renderThumb(pageIndex, dpr) | A low-level method to manually trigger the rendering of a specific thumbnail image. Returns a Task<Blob>. |
Need Help?
Join our community for support, discussions, and to contribute to EmbedPDF's development.