Print Document
v0.1.0DraftA printable book on US Letter pages: an optional cover, an optional contents page that links to each section, then one section per page. It is dumb on purpose: it lays out what it is given and knows nothing about where the text comes from.
A printable book on US Letter pages: an optional cover, an optional contents page that links to each section, then one section per page. It is dumb on purpose: it lays out what it is given and knows nothing about where the text comes from.
Each section starts a new page, the contents list carries no page numbers (a browser cannot resolve them reliably), and the optional running title repeats in the top margin of every page after the cover. The print rules use their own named page (print-document), so they never change how any other page of a site prints. On screen each page shows as a white sheet with dark text, the same as on paper, whatever the site's theme: the sheet uses the system colours Canvas and CanvasText (blended for the muted text, so it reaches WCAG AA, 4.5:1, on white) and redefines the on-surface, on-surface-variant, secondary and tertiary colour roles for what is inside it, so prose such as RichText stays readable.
The running title is printed through a page margin box, so it shows only in browsers that support them (Chromium does). A margin box can only read custom properties from the root element, so the component sets --print-document-running-title as an inline style on <html> once it has mounted. Each mounted document keeps its title in a list; when one unmounts its title leaves the list and <html> shows the last title still there, or nothing when the list is empty. This is a documented exception to the no-inline-styles rule, because there is no other way to pass a prop to a margin box. It also means no title prints before hydration or with JavaScript off, and with several documents mounted only the title of the one mounted last that is still mounted and has a title shows, whatever order they unmount in, and retitling a document does not change its place. The list lives in the module, so an app that loads both the ESM and the CJS build of the package gets two lists that overwrite each other on <html>. Registry packages ship no "use client"; an app that renders this from a server component re-exports it from its client boundary file.
Usage
The ```jsx block above runs live on the docs site. Imports are stripped and every registry export is in scope, so you can compose with other components too.
Examples
Open all 2 →Properties
PrintDocument props
| Prop | Type | Default | Description |
|---|---|---|---|
sections* | PrintDocumentSection[] | — | The sections in print order; each starts on a new page |
className | string | — | Additional class names to merge with the component root element |
cover | ReactNode | — | The cover page content. It prints on its own page with no running title. Omit it for a document without a cover |
runningTitle | string | — | Text repeated in the top margin of every page after the cover. It prints only where the browser supports page margin boxes. A page margin box inherits from the root element, so this sets the custom property `--print-document-running-title` as an inline style on `<html>` once mounted. That is a documented exception to the no-inline-styles rule: it is the only way to pass a prop to a margin box. No title prints before hydration or with JavaScript off. With several documents mounted, `<html>` holds the title of the one mounted last that is still mounted and has a title (retitling a document does not change its place), whatever order they unmount in, and nothing once none is left |
toc | string | — | The heading of the contents page, which lists every section in order with no page numbers. Omit it for no contents page |
Also accepts the native attributes of its root element (className, aria-*, event handlers, …).