0

PDF Document Grid

A grid of every open document, each card a navigable single-page preview that opens the document when picked.

"use client";

import { PdfDocumentGrid } from "@/components/pdf-document-grid";

About

<PdfDocumentGrid /> shows every open document as a card in a responsive grid. It renders each preview off embedpdf's thumbnail plugin, which can render any loaded document by id — so every card shares the one engine <PdfViewer> already runs, instead of spinning up a viewer per document.

  • Preview — each card renders one page of its document. Paging a card is local: it flips through that document's pages without touching the viewer, so the grid works as a browsable overview.
  • Select — clicking a card routes it through the view-manager into the shared view, so the <PdfViewer> (and every control bound to it) switches to that document. The selected card carries a ring.
  • Open more — a trailing card calls the document-manager's file dialog, and the newly opened document joins the grid.

Installation

pnpm dlx shadcn@latest add pdfcn/document-grid

Usage

Place <PdfDocumentGrid> inside a <PdfViewer> loaded with multiple documents, beside the viewer it drives.

<PdfViewer
  documents={[{ url: "/sample.pdf" }, { url: "/form.pdf" }]}
  className="h-[720px]"
>
  <div className="flex h-full min-h-0">
    <PdfDocumentGrid className="w-2/5 border-r" />
    <div className="flex min-w-0 flex-1 flex-col">
      <PdfToolbar>
        <PdfPageNavigation />
        <PdfZoomControls />
      </PdfToolbar>
      <PdfViewerContent />
    </div>
  </div>
</PdfViewer>

Examples

Default

Three documents load into the grid, beside a viewer. Page through a card in place, then click it to open that document in the viewer — the ring follows the open document. The trailing card opens another PDF into the grid.

"use client";

import { PdfDocumentGrid } from "@/components/pdf-document-grid";

As a launcher

Pass onSelectDocument to react when a card is picked — the library app block uses it to swap the grid for a full-screen reader of the chosen document, then back again.

const [mode, setMode] = React.useState<"library" | "reader">("library");
 
return mode === "library" ? (
  <PdfDocumentGrid onSelectDocument={() => setMode("reader")} />
) : (
  <Reader onBack={() => setMode("library")} />
);

Accessibility

Each card is a button labelled Open <name>, with focus-visible rings on both the preview and the page-step controls. The page steppers are labelled "Previous page" and "Next page" and stop the click from bubbling into the card's select, so paging never opens the document. The trailing card is labelled "Open another PDF".

API Reference

PdfDocumentGrid

A <div> carrying data-slot="pdf-document-grid". Enumerates every open document and renders each as a card. Accepts every prop a <div> takes, plus:

PropTypeDefaultDescription
minCardWidthnumber200Smallest a card gets before the grid drops a column, in pixels. Drives the layout.
gapnumber16The gutter between cards, in pixels.
showAddCardbooleantrueRender the trailing card that opens another document.
onSelectDocument(documentId: string) => voidCalled with a document's id when its card is picked, after selection is routed.