PDF Shortcuts Dialog

A ?-triggered cheatsheet listing every keyboard shortcut the viewer has bound.

"use client";

import { createPluginRegistration } from "@embedpdf/core";

About

The ? overlay, the way Linear and GitHub do it. It reads the live command registry, so it lists what this app can do rather than what a preset defines — a command whose plugin was never registered is left out.

Optional. Pair it with PDF Keyboard Shortcuts, which binds the keys; they work with or without this mounted.

Installation

pnpm dlx shadcn@latest add @pdfviewcn/shortcuts-dialog

Usage

import { PdfShortcutsDialog } from "@/components/pdf-shortcuts-dialog";
<PdfViewer documents={[{ url: "/sample.pdf" }]} plugins={plugins}>
  <PdfToolbar>
    <div className="ml-auto">
      <PdfShortcutsDialog />
    </div>
  </PdfToolbar>
  <PdfViewerContent />
</PdfViewer>

plugins has to carry createKeyboardShortcutsRegistration() — see Usage. Without it the sheet opens empty and says so.

The list is taken fresh on every open, so a search panel or layout that mounted after the dialog still shows up.

Examples

Default

"use client";

import { createPluginRegistration } from "@embedpdf/core";

Without a trigger

? opens it from anywhere in the viewer, so the button is optional:

<PdfShortcutsDialog trigger={null} />

Custom trigger

<PdfShortcutsDialog trigger={<Button variant="outline">Shortcuts</Button>} />

Section order

<PdfShortcutsDialog categoryOrder={["Tools", "Editing", "Navigation"]} />

Unlisted categories trail after in registration order.

Accessibility

The default trigger is a button labelled Keyboard shortcuts, so the label survives without the tooltip. Focus, Esc, and the return of focus on close come from Dialog.

Each category is a <section> with a heading, so the sheet reads as a list of groups rather than one run of rows. Keys are <Kbd> elements — announced as text, not images.

? is bound by the preset's global listener, which ignores keystrokes in inputs, so typing ? into a search field won't open it.

API Reference

PdfShortcutsDialog

Renders the cheatsheet with data-slot="pdf-shortcuts-dialog" on the content, and each row as data-slot="pdf-shortcuts-dialog-row". Extends Dialog, so open, defaultOpen, and onOpenChange pass through.

PropTypeDefaultDescription
triggerReact.ReactElement | nullkeyboard buttonElement that opens the dialog. null renders none — ? still opens it.
categoryOrderstring[]Nav, Zoom, …Category order, top to bottom. Unlisted categories trail after.

Commands sharing a label fold into one row and pool their keys, which is why the four nudge directions read as on one line.

A command that reports itself invisible is dropped; one that's merely disabled right now — Delete with nothing selected — keeps its row, so the sheet doesn't rewrite itself while it's being read. See What each app gets.