0

PDF More Actions Menu

An overflow menu for the toolbar actions that don't earn an icon, plus the document properties dialog it opens.

"use client";

import { PdfMoreActionsMenu } from "@/components/pdf-more-actions-menu";

About

<PdfMoreActionsMenu /> is the "⋮" at the end of a toolbar: print, first and last page, rotation, scroll direction, pan, page layout, presentation mode, opening a file, and document properties. It's one control over eight plugin hooks, for the actions a toolbar can't spare an icon for.

Every item here also exists as a standalone control — <PdfRotateButton />, <PdfSpreadToggle />, <PdfPanToggle />, <PdfPrintButton />, <PdfFullscreenToggle />, <PdfOpenFileButton />. This is a second composition over the same hooks, not a replacement for them. Render whichever fits the width you have.

Installation

pnpm dlx shadcn@latest add pdfcn/more-actions-menu

Usage

import { PdfMoreActionsMenu } from "@/components/pdf-more-actions-menu";
<PdfViewer documents={[{ url: "/sample.pdf" }]} className="h-[720px]">
  <PdfToolbar>
    <PdfPageNavigation />
    <PdfToolbarSeparator />
    <PdfZoomControls />
    <PdfMoreActionsMenu className="ml-auto" />
  </PdfToolbar>
  <PdfViewerContent />
</PdfViewer>

The root renders no element of its own, so className lands on the "⋮" trigger — the only part a layout needs to position.

<PdfDocumentPropertiesDialog /> ships in the same file. The menu mounts it itself, because "Document properties…" needs somewhere to go; you only import it separately to put the dialog in a toolbar without the rest of the menu.

Examples

Default

"use client";

import { PdfMoreActionsMenu } from "@/components/pdf-more-actions-menu";

Single-document viewer

closeExisting closes what's open before the picker appears, so exactly one document ends up loaded. It mirrors <PdfOpenFileButton />'s prop of the same name, and it's how the viewer app keeps a single-document layout single.

<PdfMoreActionsMenu closeExisting />

Leave it off for a tabbed host like the workspace app, where a new file should open alongside what's already there.

Properties without the menu

The dialog stands alone as its own icon button, for a toolbar wide enough to show properties directly:

<PdfToolbar>
  <PdfPageNavigation />
  <div className="ml-auto flex items-center gap-1">
    <PdfDocumentPropertiesDialog />
    <PdfPrintButton />
  </div>
</PdfToolbar>

Pass trigger to open it from something else — a menu item, a link, a button of your own:

<PdfDocumentPropertiesDialog
  trigger={<Button variant="outline">Details</Button>}
/>

Accessibility

The trigger is a real <button> carrying aria-label="Open more actions menu", matching its tooltip, so the label is available whether or not the tooltip is shown.

The menu itself is shadcn's <DropdownMenu />: and move between items, Enter activates, Esc closes and returns focus to the trigger. Presentation mode and pan are checkbox items; scroll direction and page layout are radio groups, so a screen reader announces which of each set is current.

Items whose plugin isn't ready — or whose document hasn't loaded — render disabled rather than absent, so the menu keeps its shape and its item order as a document opens.

"Document properties…" opens its dialog a tick after the menu closes. Opening both in the same tick races the menu returning focus to its trigger against the dialog trapping it, and focus can end up on a menu that's already gone.

API Reference

PdfMoreActionsMenu

A <DropdownMenu /> whose trigger is a ghost icon button carrying data-slot="pdf-more-actions-menu-trigger". Accepts every <DropdownMenu /> prop, plus:

PropTypeDefaultDescription
closeExistingbooleanfalseClose every open document before showing the file picker, so exactly one ends up loaded.
classNamestringApplied to the "⋮" trigger. The root renders no element of its own.

PdfDocumentPropertiesDialog

A <Dialog /> of the active document's PDF properties. The property list inside is <PdfDocumentInfo /> — the same panel the library browser shows in its sidebar, so the two never drift apart. Accepts every <Dialog /> prop except children, plus:

PropTypeDefaultDescription
triggerReact.ReactElement | nulldefault icon buttonThe element that opens the dialog. null renders no trigger, for driving it with open/onOpenChange.

Presentation mode and Open PDF file…

Two items work with no document loaded at all — presentation mode belongs to the viewer, and opening a file has to work before anything is open, which is the one moment it matters most. Both are enabled as soon as their plugin is ready.

Everything else is document-scoped. embedpdf's document-scoped hooks throw when handed a document with no plugin state yet, so those items mount separately and swap for a disabled set until a document resolves — the same split every control in PDF Toolbar uses, applied to part of a menu rather than a whole component.

Scroll direction

embedpdf exposes a setter for the scroll strategy but no reactive getter, so the radio group tracks the last selection made here rather than reading the engine back. Setting the strategy elsewhere won't move the mark. The plugin defines two strategies — vertical and horizontal — so there are no PDF.js-style wrapped or single-page modes to offer.