0

PDF Bookmark Sidebar

A navigable outline of a document's bookmarks.

"use client";

import { PdfBookmarkSidebar } from "@/components/pdf-bookmark-sidebar";

About

<PdfBookmarkSidebar /> reads the outline a PDF ships with — the tree of titles its author wrote into the file — and turns each entry into a button that scrolls the viewer to its destination.

Many PDFs have no outline, so the sidebar shows an empty state rather than collapsing the column out of your layout.

Installation

pnpm dlx shadcn@latest add pdfcn/bookmark-sidebar

Usage

import { PdfBookmarkSidebar } from "@/components/pdf-bookmark-sidebar";
<PdfViewer documents={[{ url: "/sample.pdf" }]} className="h-[600px] flex-row">
  <PdfBookmarkSidebar className="w-56 shrink-0 border-r" />
  <PdfViewerContent />
</PdfViewer>

<PdfViewer /> is a flex column by default, which stacks a sidebar above the document. Override it with flex-row to put them side by side, and give the sidebar a width — it fills its parent's height but has no width of its own.

The bookmark plugin is part of the light tier <PdfViewer /> already registers, so nothing needs to be added to plugins.

Examples

Default

"use client";

import { PdfBookmarkSidebar } from "@/components/pdf-bookmark-sidebar";

Accessibility

The list is wrapped in a <nav aria-label="Document outline"> so it's reachable as a landmark, and rendered as nested <ul>/<li> elements so the outline's depth is conveyed structurally rather than by indentation alone. Every entry is a real <button>, reachable with Tab.

Entries that point at something other than a page destination — an external URL, an embedded action — are rendered disabled rather than hidden, so the outline still matches the document's own structure.

API Reference

PdfBookmarkSidebar

A <ScrollArea /> carrying data-slot="pdf-bookmark-sidebar", containing the outline tree. Accepts every <ScrollArea /> prop.

Fetches the outline once per document through the bookmark plugin's capability, and scrolls the viewer via useScroll when an entry is clicked. It has no width of its own and fills its parent's height.

The sidebar renders in three states, all at the same size: empty while the document loads, a message when the document has no outline, and the tree itself otherwise.

Styling the tree

The rendered markup carries slots at each level, so the tree can be restyled without forking the component:

SlotElementDescription
pdf-bookmark-sidebardivThe scroll container.
pdf-bookmark-listulOne per level, including the root.
pdf-bookmark-itembuttonA single outline entry.

Nested lists are indented with a left border. Depth is unbounded — the list renders itself recursively for as many levels as the document declares.