Skip to content

feat(viewer): Phase 2a DocumentFrame owns PDF zoom/fit chrome - #1687

Merged
BigSimmo merged 9 commits into
mainfrom
cursor/viewer-phase2a-frame-controls-1db8
Aug 7, 2026
Merged

feat(viewer): Phase 2a DocumentFrame owns PDF zoom/fit chrome#1687
BigSimmo merged 9 commits into
mainfrom
cursor/viewer-phase2a-frame-controls-1db8

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Summary

  • Phase 2a of the unified viewer chrome plan (docs/plans/document-viewer-phase2-unified-chrome.md): DocumentFrame owns zoom / fit-width / viewing-aid for canvas PDF.
  • Shared zoom contract in viewer-zoom.ts (0.55–4, step 0.15) used by Frame defaults and PdfCanvasViewer.
  • PdfCanvasViewer accepts controlled fit/zoom; when Frame owns chrome, demotes duplicate toolbar zoom/fit while keeping page nav, rotate, and fullscreen.
  • Contract test flipped to require controls={pdfFrameControls} for the canvas PDF path.

Verification

  • Focused / filtered unit+DOM: tests/document-frame-contract.test.ts, document-frame.dom.test.tsx, property-document-frame.dom.test.tsx, document-viewer-shell.dom.test.tsx, document-viewer-pdf-reader-lazy.test.ts, client-performance-boundaries.test.ts, document-detail-performance.test.ts7 passed (32 tests)
  • npm run verify:pr-local — exit 0
    • Decisive: Test Files 520 passed (520) / Tests 5532 passed | 1 skipped (5533)
    • Decisive: Offline RAG fixture and manifest validation passed (36 golden cases, 23 suites).
  • UI verification not run: chrome ownership moved within existing document preview; phone composer/reserves unchanged. Prefer npm run ensure + manual PDF smoke before widening to verify:ui.
  • Release verification not run: not a release claim.

Risk and rollout

  • Risk: dual zoom chrome or mismatched zoom ranges; mitigated by demoting PDF zoom/fit in the same change that wires Frame controls and sharing clamp/step constants.
  • Rollback: revert this PR; canvas PDF falls back to previous toolbar-owned zoom/fit.
  • Provider or production effects: None

Clinical Governance Preflight

  • Source-backed claims still require linked source verification before clinical use
  • No patient-identifiable document workflow was introduced or expanded without explicit governance approval
  • Supabase target remains Clinical KB Database (sjrfecxgysukkwxsowpy)
  • Service-role keys and private document access remain server-only
  • Demo/synthetic content remains clearly separated from real clinical sources
  • Source metadata, review status, and outdated/unknown-source behavior remain conservative
  • Deployment classification/TGA SaMD impact was checked when clinical decision-support behavior changed

Notes

  • RAG impact: no retrieval behaviour change — source preview chrome only; ranking/retrieval surfaces untouched.
  • Does not start 2b (photo lightbox), 2c (filmstrip), 2d/2e.
  • Flightplan classified ui; treated as UI + clinical document surface for governance.
Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features

    • Added consistent PDF zoom controls with fit-to-width support.
    • Zoom levels now use shared minimum, maximum, default, and step values.
    • Added a dedicated fullscreen document-view control.
    • PDF zoom and viewing settings reset when switching documents.
  • Bug Fixes

    • Improved zoom handling for keyboard, gesture, and repeated updates.
    • Ensured zoom values remain within supported limits.

Phase 2a: wire shared viewer zoom contract into DocumentFrame controls,
control PdfCanvasViewer fit/zoom from the parent, and demote duplicate
pdf-toolbar zoom/fit chrome while keeping page/rotate/fullscreen.
Adjust fit/zoom/viewing-aid during render when documentId changes so the
static guard's react-hooks/set-state-in-effect rule stays green.
@supabase

supabase Bot commented Aug 7, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project sjrfecxgysukkwxsowpy because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 6 minutes

Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2a305737-c183-49e9-8af0-666e41f3389b

📥 Commits

Reviewing files that changed from the base of the PR and between 598fb2f and bd65796.

📒 Files selected for processing (2)
  • src/components/document-viewer/pdf-canvas-viewer.tsx
  • tests/ui-smoke.spec.ts
📝 Walkthrough

Walkthrough

DocumentViewer now owns PDF fit-width, zoom, and viewing-aid state. PdfCanvasViewer accepts controlled values and callbacks. Shared zoom constants and utilities replace local values. Controls and tests now use the updated zoom steps and fullscreen label.

Changes

PDF viewer controls

Layer / File(s) Summary
Shared zoom contract
src/components/document-viewer/viewer-zoom.ts, src/components/ui/document-frame.tsx, tests/viewer-zoom.test.ts
Shared constants and helpers define zoom bounds, defaults, increments, and functional updates. DocumentFrame uses these values.
Controlled canvas viewer
src/components/document-viewer/pdf-canvas-viewer.tsx, tests/document-frame.dom.test.tsx, tests/property-document-frame.dom.test.tsx
PdfCanvasViewer supports controlled fit-width and zoom state, shared clamping, debounced rendering, gesture and keyboard updates, and separate fullscreen entry.
Document viewer wiring
src/components/DocumentViewer.tsx, tests/document-frame-contract.test.ts, tests/ui-smoke.spec.ts
DocumentViewer resets document-scoped PDF state, gates controls on readiness, and passes state and callbacks through DocumentFrame to PdfCanvasViewer. Contract and smoke tests use the updated wiring and label.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DocumentViewer
  participant DocumentFrame
  participant PdfCanvasViewer
  DocumentViewer->>DocumentFrame: pass PDF controls
  DocumentFrame->>PdfCanvasViewer: pass controlled fit-width and zoom
  PdfCanvasViewer->>DocumentViewer: report fit-width and zoom changes
  DocumentViewer->>DocumentFrame: update control state
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: DocumentFrame now owns PDF zoom and fit controls.
Description check ✅ Passed The description covers the required summary, verification, risk, rollback, governance, and notes sections with clear evidence and exceptions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/viewer-phase2a-frame-controls-1db8

Comment @coderabbitai help to get the list of available commands.

@BigSimmo
BigSimmo marked this pull request as ready for review August 7, 2026 13:09
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

Comment thread src/components/document-viewer/pdf-canvas-viewer.tsx
@BigSimmo

BigSimmo commented Aug 7, 2026

Copy link
Copy Markdown
Owner Author

@cursoragent please resolve all comments and issues for this PR

@cursor

cursor Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Resolved the only actionable review thread on #1687.

Sentry HIGH (stale setZoom): Valid — wheel/pinch use functional updaters, and the old code resolved them against a closed-over zoom, so rapid steps dropped (worse on the Frame-owned path). Fixed by composing through an eager zoomRef when Frame owns chrome, and React’s setInternalZoom updater otherwise; same pattern for setFitWidth. Added resolveViewerZoomUpdate plus unit/contract coverage.

Other PR comments: Informational only (Supabase no-op, CodeRabbit rate limit, Codex review quota) — nothing to change.

Evidence: npx vitest run tests/viewer-zoom.test.ts tests/document-frame-contract.test.tsTest Files 2 passed (2) / Tests 7 passed (7). Review thread resolved on head 598fb2f11b7f248856a02b3b6ae75bc69faed010.

Open in Web Open in Cursor 

Pinch/wheel use functional setZoom updaters; resolving against a closed-over
zoom dropped intermediate steps. Compose via zoomRef (Frame-owned) and React
state updaters (internal), plus resolveViewerZoomUpdate tests.
@BigSimmo
BigSimmo enabled auto-merge (squash) August 7, 2026 13:32

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/document-viewer/pdf-canvas-viewer.tsx`:
- Around line 106-107: Move the fitWidthRef and zoomRef assignments out of the
render body and into a commit-time layout effect so discarded renders cannot
update refs; retain immediate ref writes in the setFitWidth and setZoom event
handlers before propagating changes to DocumentViewer.
🪄 Autofix

✅ Autofix completed


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 44cd04b4-9efb-46e0-a982-07dba58cfc19

📥 Commits

Reviewing files that changed from the base of the PR and between da66b28 and 598fb2f.

📒 Files selected for processing (9)
  • src/components/DocumentViewer.tsx
  • src/components/document-viewer/pdf-canvas-viewer.tsx
  • src/components/document-viewer/viewer-zoom.ts
  • src/components/ui/document-frame.tsx
  • tests/document-frame-contract.test.ts
  • tests/document-frame.dom.test.tsx
  • tests/property-document-frame.dom.test.tsx
  • tests/ui-smoke.spec.ts
  • tests/viewer-zoom.test.ts

Comment thread src/components/document-viewer/pdf-canvas-viewer.tsx Outdated
@BigSimmo
BigSimmo disabled auto-merge August 7, 2026 13:34
@BigSimmo
BigSimmo enabled auto-merge (squash) August 7, 2026 13:55
@BigSimmo
BigSimmo requested a lite review from Copilot August 7, 2026 13:56
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Fixes Applied Successfully

Fixed 1 file(s) based on 1 unresolved review comment.

Files modified:

  • src/components/document-viewer/pdf-canvas-viewer.tsx

Commit: 4f31290e84e8f4a3e5b47334291c072f548dfd1e

The changes have been pushed to the cursor/viewer-phase2a-frame-controls-1db8 branch.

Time taken: 2m 35s

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

Implements Phase 2a of the “unified viewer chrome” plan by moving PDF zoom/fit/viewing-aid chrome ownership to DocumentFrame for the canvas-based PDF path, while keeping PdfCanvasViewer responsible for page navigation, rotation, and fullscreen.

Changes:

  • Introduces a shared zoom contract (viewer-zoom.ts) and updates both DocumentFrame and PdfCanvasViewer to use the same clamp/step/defaults.
  • Makes PdfCanvasViewer optionally controlled for fitWidth/zoom, and demotes its duplicate toolbar zoom/fit controls when DocumentFrame owns the chrome.
  • Updates contract + DOM + Playwright smoke tests to enforce the new ownership and updated accessible labels.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.

Show a summary per file
File Description
tests/viewer-zoom.test.ts Adds unit coverage for shared clamp/functional zoom update composition.
tests/ui-smoke.spec.ts Updates fullscreen button accessible name expectation for the PDF canvas toolbar.
tests/property-document-frame.dom.test.tsx Adjusts minimum zoom expectation to align with the shared zoom contract (55%).
tests/document-frame.dom.test.tsx Updates expected zoom step deltas (±0.15) for frame-owned controls.
tests/document-frame-contract.test.ts Tightens contract to require controls={pdfFrameControls} and shared zoom imports/behavior.
src/components/ui/document-frame.tsx Uses shared viewer zoom constants as default min/max/step for frame controls.
src/components/DocumentViewer.tsx Adds controlled PDF viewing state (fit/zoom/viewing-aid) and wires it into DocumentFrame + PdfCanvasViewer.
src/components/document-viewer/viewer-zoom.ts Defines shared viewer zoom constants plus clamp/functional-update resolver.
src/components/document-viewer/pdf-canvas-viewer.tsx Accepts controlled fit/zoom, composes functional zoom updates safely, and demotes duplicate zoom/fit toolbar when frame-owned.

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

coderabbitai Bot and others added 3 commits August 7, 2026 14:02
Fixed 1 file(s) based on 1 unresolved review comment.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
Prettier reported style issues on the Phase 2a frame chrome file,
failing format:changed in CI.
@BigSimmo
BigSimmo merged commit 842db18 into main Aug 7, 2026
25 of 26 checks passed
@BigSimmo
BigSimmo deleted the cursor/viewer-phase2a-frame-controls-1db8 branch August 7, 2026 14:54
@BigSimmo

BigSimmo commented Aug 7, 2026

Copy link
Copy Markdown
Owner Author

Autopilot + Bugbot — PR #1687

Head: bd65796329f832af7dbccedcde69a2717df7e018 (cursor/viewer-phase2a-frame-controls-1db8)
Base: main · Mergeable: clean merge-tree · Behind/ahead: 0 / 9

Snapshot

Item Result
Conflicts None — leave (already synced; tip includes merge of main)
Unresolved review threads 0
Required CI GreenPR required, Static PR, Build, Unit coverage, Safety, Production UI critical + shards
Advisory Lighthouse budget (advisory) fail — evidence incomplete (desktop-dsm missing LCP/CLS); not a required gate; unrelated to viewer chrome

Tip history this pass

  • Started against stated 4f31290…; GitHub had already moved to format fix 5c10730…, then main-merge bd65796…. Re-snapshotted each time.

Review

  • Bugbot subagent: unavailable (usage limit) — did not run.
  • Manual high-confidence delta review (DocumentViewer / PdfCanvasViewer / DocumentFrame / viewer-zoom): no P0/P1 found on current tip. Prior Sentry HIGH stale setZoom composition already fixed (598fb2f); Static format already fixed (5c10730). Phone composer/reserves untouched.
  • RAG surfaces: not touched.

Actions

  • Isolated worktree only; main-checkout WIP preserved.
  • No conflict merge, no force-push, no rebase, no auto-merge, no provider gates.
  • No code push this pass (nothing left to fix).
  • Ledger: recorded locally at this HEAD/scope (ledger:append); not pushed (avoids ledger-only tip churn).

Blockers

None for required CI. Human merge/approval still yours — not merged.

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.

3 participants