Catalog Documents

<.pdf_viewer>

ConnieUI.Documents

Loading document…

HEEx
<div class="w-2xl">
  <ConnieUI.Documents.pdf_viewer id="catalog-pdf" url="/pg/documents/director-agreement.pdf">
    <:fallback>
      <.link href={@controls[:url]} class="text-sm font-semibold text-brand-secondary underline">
        Open PDF
      </.link>
    </:fallback>
  </ConnieUI.Documents.pdf_viewer>
</div>

Controls

:string
:string

Signed URL to the PDF; component shows a loading placeholder until set.

:string

Tailwind class string applied to each rendered PDF page. Override with `pdf_letter_doc_class()` for paper-style chrome on signing pages, or a custom string when the surrounding sheet supplies its own chrome.

Docs

Renders a PDF in a scrollable page layout. Pages are lazily rendered as they enter the viewport (and ±1 viewport via `IntersectionObserver`), each rasterized to an `<img>` so they survive browser GC under memory pressure. The component is responsive: pages scale with the container width, and re-rasterize at the new resolution after the user pauses resizing. A new `url` attribute reloads the document. The element is `phx-update="ignore"`, so LiveView on its own only patches its `data-*` attributes: a changed `url` assign reaches it only when the host's LiveSocket passes the `dom` callbacks from `assets/js/cui_dom.js`, which sync every attribute of a `cui-*` element (connie and the e2e harness do). pdf.js is loaded by URL from `/assets/pdfjs/`, which the host serves: `pdf.min.mjs` and `pdf.worker.min.mjs` from pdfjs-dist's `build/`, and the same two files from its `legacy/build/` under `/assets/pdfjs/legacy/`. The legacy build is chosen in any browser that lacks an API the modern one calls natively. When pdf.js fails to load the document or render its first pages, or makes no progress for 30 seconds while the page is visible, the placeholder is removed and the `:fallback` slot is shown. The element dispatches `cui-pdf-viewer:loaded` (`detail: %{build}`) once the first pages are shown, or `cui-pdf-viewer:error` (`detail: %{build, stage, reason, message}`) when it gives up. Both bubble. `stage` is where it failed (`"library"`, `"document"` or `"render"`) and `reason` the error's name (`"stalled"` for the timeout); neither carries anything from the document. `message` is the error's own text, which can include the document's URL. ## Examples <ConnieUI.Documents.pdf_viewer url={@pdf_url} /> <ConnieUI.Documents.pdf_viewer url={@pdf_url} doc_class={ConnieUI.Documents.pdf_letter_doc_class()} > <:fallback> <a href={@pdf_url}>Open PDF</a> </:fallback> </ConnieUI.Documents.pdf_viewer>
Attribute Type Default Description
id :string "cui-pdf-viewer"
url :string nil
Signed URL to the PDF; component shows a loading placeholder until set.
doc_class :string "template mt-12 first:mt-0 rounded-lg shadow-lg ring-1 ring-black/5 bg-white overflow-hidden"
Tailwind class string applied to each rendered PDF page. Override with `pdf_letter_doc_class()` for paper-style chrome on signing pages, or a custom string when the surrounding sheet supplies its own chrome.
rest :global
Set on the `cui-pdf-viewer` element, e.g. a `data-*` attribute that names the page for a host listening to its events.
Slot Slot attributes Description
:fallback Shown in place of the pages when the browser cannot load or render the PDF, e.g. links to open or download it. Rendered with the page and kept hidden until then. LiveView does not patch inside the viewer, so the content is fixed for the element's lifetime: a caller whose `url` changes to another document keys the viewer's `id` by it.