Skip to content

feat(canvas): export canvas dashboards as PDF#9593

Open
nishantmonu51 wants to merge 9 commits into
mainfrom
canvas_pdf_export
Open

feat(canvas): export canvas dashboards as PDF#9593
nishantmonu51 wants to merge 9 commits into
mainfrom
canvas_pdf_export

Conversation

@nishantmonu51

Copy link
Copy Markdown
Collaborator

Adds a PDF tab to the share popover for canvas dashboards, allowing users to export the rendered canvas as a downloadable PDF.

  • New web-common/src/features/exports/pdf/ module: captures the canvas, expands tables, settles async rendering, lays out pages, and assembles the PDF via jspdf.
  • ShareDashboardPopover gains a "PDF" tab, shown only for canvas dashboards (when canvasName and instanceId are provided).
  • CanvasDashboardWrapper renders an off-screen CanvasPdfExportHeader used solely as the PDF capture target.
  • Adds jspdf dependency.

Checklist:

  • Covered by tests
  • Ran it and it works as intended
  • Reviewed the diff before requesting a review
  • Checked for unhandled edge cases
  • Linked the issues it closes
  • Checked if the docs need to be updated. If so, create a separate Linear DOCS issue
  • Intend to cherry-pick into the release branch
  • I'm proud of this work!

Developed in collaboration with Claude Code

nishantmonu51 and others added 3 commits June 19, 2026 21:33
Add a "PDF" tab to the share popover for canvas dashboards that captures
the rendered canvas and assembles it into a downloadable PDF.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a client-side “Export as PDF” flow for canvas dashboards, integrating a new PDF export module in web-common and exposing it via a new “PDF” tab in the share popover for canvas dashboards.

Changes:

  • Introduces a new web-common/src/features/exports/pdf/ module to settle rendering, capture canvas blocks, paginate, and assemble/download a PDF via jspdf.
  • Updates the share UI to show a “PDF” tab only when canvas identifiers are present, and wires it to the canvas PDF export orchestrator.
  • Adds an off-screen, read-only canvas header render (CanvasPdfExportHeader) as a capture target and adds the jspdf dependency.

Reviewed changes

Copilot reviewed 15 out of 16 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
web-common/src/features/exports/pdf/types.ts Adds shared PDF export types and capture block schema.
web-common/src/features/exports/pdf/settle.ts Adds “settle before capture” utilities for stores, queries, and fonts.
web-common/src/features/exports/pdf/layout.ts Implements pagination/layout logic for captured blocks across PDF pages.
web-common/src/features/exports/pdf/layout.spec.ts Adds vitest coverage for pagination/orientation behavior.
web-common/src/features/exports/pdf/filename.ts Adds filename slug + timestamp helper for PDF downloads.
web-common/src/features/exports/pdf/ExportPdfOptions.svelte Adds share-popover UI for running the PDF export with options/progress.
web-common/src/features/exports/pdf/export-canvas-pdf.ts Orchestrates canvas-to-PDF export (settle → capture → paginate → assemble).
web-common/src/features/exports/pdf/capture.ts Captures filter header + component cards into raster blocks for PDF assembly.
web-common/src/features/exports/pdf/CanvasPdfExportHeader.svelte Off-screen read-only header (time range + filters) for capture.
web-common/src/features/exports/pdf/assemble.ts Renders paginated placements into a jsPDF document and triggers download.
web-common/src/features/exports/pdf/assemble.spec.ts Adds tests for background color parsing used in PDF rendering.
web-common/src/features/canvas/CanvasDashboardWrapper.svelte Mounts the off-screen PDF header capture target for canvases.
web-common/package.json Adds jspdf dependency.
web-admin/src/features/projects/ProjectHeader.svelte Passes canvasName/instanceId to enable the PDF tab for canvas dashboards.
web-admin/src/features/dashboards/share/ShareDashboardPopover.svelte Adds “PDF” tab + hooks it up to exportCanvasPdf.
package-lock.json Updates lockfile for the new dependency and transitive packages.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread web-common/src/features/exports/pdf/settle.ts
Comment thread web-common/src/features/exports/pdf/CanvasPdfExportHeader.svelte
Comment thread web-common/src/features/exports/pdf/layout.spec.ts Outdated
capture.spec.ts uses the DOM (document) but is batched with pure-logic
specs in the same directory. Under vitest's parallel forks pool the
jsdom global was intermittently unavailable, causing 'document is not
defined'. Pin the spec to the jsdom environment to make it deterministic.
The off-screen canvas PDF export header was always mounted, so its
read-only filter chips duplicated the live filter bar's text and the
'Readonly Filter Chips' aria-label. Off-screen positioning still counts
as visible/queryable to Playwright, so this caused strict-mode
violations in unrelated canvas e2e tests (web-local default-filters,
web-admin bookmarks).

Keep it display:none in normal use (excluded from the a11y tree and
text/label locators) and have capture.ts reveal it only while measuring
and rasterizing.
The previous display:none approach did not work: Playwright locators
(getByText/getByLabel) and the accessibility tree match elements
regardless of CSS visibility, so the always-mounted off-screen header
still duplicated the live filter bar's text and 'Readonly Filter Chips'
label, failing web-local default-filters and web-admin bookmarks e2e
tests with strict-mode violations.

Gate the header behind a canvasPdfExportActive store so it only exists
in the DOM during an active export (mirroring the ScreenshotContainer
dialog pattern). prepareCanvasForCapture's tick() flushes it into the
DOM before capture reads it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants