Skip to content

improvement(files): fit-width previews and chip-chrome viewer controls#5002

Merged
waleedlatif1 merged 4 commits into
stagingfrom
feat/file-viewer-experience
Jun 12, 2026
Merged

improvement(files): fit-width previews and chip-chrome viewer controls#5002
waleedlatif1 merged 4 commits into
stagingfrom
feat/file-viewer-experience

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • PDF and DOCX previews now treat 100% zoom as fit-to-width instead of capping at the page's natural print size — removes the dead side gutters in wide panels and shrinks the empty space below short docs (pdf.js re-renders the canvas at the target width and DOCX scales via CSS zoom, so both stay crisp)
  • PreviewToolbar page/zoom controls migrate from 24px ghost Buttons with off-token labels (text-[12px] --text-secondary) to canonical emcn chips — icon-only Chip pills with text-sm --text-body value labels
  • XLSX sheet tabs migrate from underline-style ghost Buttons to a chip cluster using the active pill state
  • Audio preview swaps the 🎵 emoji for the lucide Music icon on design-system tokens

Type of Change

  • Improvement

Testing

Mounted the real FileViewer against sample files for every preview type (pdf wide + narrow, docx, xlsx multi-sheet, image, audio) in a headless browser with the app's color tokens — all render clean with zero console errors; screenshots verified fit-width behavior and chip chrome. 138 file-viewer tests pass; tsc --noEmit and biome check clean.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

- PDF and DOCX previews now treat 100% zoom as fit-to-width instead of
  capping at the page's natural print size, removing the dead gutters in
  wide panels (pdf.js re-renders the canvas at the target width and DOCX
  uses CSS zoom, so both stay crisp)
- PreviewToolbar page/zoom controls move from 24px ghost Buttons with
  off-token labels to canonical emcn chips (icon-only Chip pills, text-sm
  --text-body value labels)
- XLSX sheet tabs move from underline-style ghost Buttons to a chip
  cluster using the active pill state
- Audio preview swaps the music emoji for the lucide Music icon on
  design-system tokens
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@vercel

vercel Bot commented Jun 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jun 12, 2026 6:51pm

Request Review

@cursor

cursor Bot commented Jun 12, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Scoped to workspace file preview UI and layout; no auth, data, or API changes beyond safer PDF buffer handling for pdf.js workers.

Overview
PDF and DOCX workspace previews now treat 100% zoom as fit-to-width: PDF drops the max page width cap so pages use the panel width (minus padding), and DOCX stops capping fit scale at 1 so wide panels can upscale pages via CSS zoom—aligned semantics and fewer side gutters.

Both viewers debounce resize handling (~150ms) so dragging a panel divider does not refit/re-raster on every frame; PDF still applies the first non-zero width immediately.

Preview chrome moves to design-system Chip controls: shared PreviewToolbar page/zoom actions and XLSX sheet tabs (with active state) replace ghost Buttons. Audio/video previews are unified in MediaPreview; audio uses the lucide Music icon instead of an emoji.

Reviewed by Cursor Bugbot for commit 6a33064. Configure here.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 62d12a0. Configure here.

@greptile-apps

greptile-apps Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR removes the fixed-width cap from PDF and DOCX previews so 100% zoom fills the panel width, debounces the DOCX ResizeObserver to match the previously reviewed PDF change, consolidates AudioPreview/VideoPreview into a unified MediaPreview, and migrates toolbar/tab chrome from legacy Button to the canonical Chip component.

  • Fit-to-width: PDF_PAGE_MAX_WIDTH (816 px) removed from pdf-viewer.tsx; Math.min(1, …) removed from fitDocxToContainer — pdf.js re-rasters at the target pixel width and DOCX uses CSS zoom, so both stay crisp when upscaling past the natural print size.
  • ResizeObserver debounce (DOCX): Mirrors the already-merged PDF fix — first non-zero measurement is applied immediately; subsequent ones (panel-divider drags) are coalesced at 150 ms with correct clearTimeout cleanup on teardown.
  • MediaPreview unification: Blob-URL lifecycle, MIME fallback, and error/loading handling were identical in the two old components; merging them removes duplication. The Music lucide icon replaces the 🎵 emoji using design-system colour tokens.
  • Chip migration: PreviewToolbar nav/zoom buttons and XLSX sheet tabs now use the canonical Chip pill; disabled propagates via the native button attribute, active drives the selected-sheet highlight, and overflow-x-auto + shrink-0 handles wide multi-sheet workbooks.

Confidence Score: 5/5

Safe to merge — all changes are UI-layer improvements with no data-path or auth impact.

The fit-to-width changes are straightforward math (removing a cap), the debounce mirrors a pattern already reviewed and merged, the MediaPreview consolidation is a pure code-quality refactor with identical runtime behaviour, and the Chip migration follows the design-system conventions correctly. No regressions or logic gaps were found across the five changed files.

No files require special attention.

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/pdf-viewer.tsx Removes the 816 px width cap, making 100% zoom fit-to-width; replaces ResizeObserver with a correctly debounced version (first non-zero measurement is immediate, subsequent ones are coalesced at 150 ms) — no logic issues found.
apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/docx-preview.tsx Mirrors the PDF debounce pattern for the DOCX ResizeObserver and removes the Math.min(1, …) cap so pages upscale past their natural print width; cleanup via clearTimeout on teardown is correct.
apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/file-viewer.tsx Consolidates AudioPreview and VideoPreview into a single MediaPreview component; blob-URL lifecycle, MIME fallback, error handling, and loading states are all preserved correctly; Music icon replaces the emoji.
apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-toolbar.tsx Button → Chip migration uses the correct canonical props (leftIcon, disabled, aria-label); disabled state propagates through the button's native attribute; cn import is still needed and retained.
apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/xlsx-preview.tsx Sheet tabs migrate from underline-style ghost Buttons to Chip with the active prop; overflow-x-auto + shrink-0 correctly handles wide multi-sheet workbooks; unused cn import removed cleanly.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    FV[FileViewer] -->|kind='audio'| MP[MediaPreview]
    FV -->|kind='video'| MP
    MP --> BU[useBlobUrl]
    BU --> UE[useEffect: createObjectURL]
    UE -->|kind='audio'| AP[Audio player + Music icon]
    UE -->|kind='video'| VP[Video player]

    PDF[PdfViewerCore] --> RO_PDF[ResizeObserver]
    RO_PDF -->|first non-zero| IMM[setContainerWidth immediately]
    RO_PDF -->|subsequent| DB_PDF[debounce 150ms → setContainerWidth]
    DB_PDF --> PW[pageWidth = containerWidth - 2×padding no max-width cap]

    DOCX[DocxPreview] --> RO_DOCX[ResizeObserver]
    RO_DOCX --> DB_DOCX[debounce 150ms → applyPostRenderStyling]
    DB_DOCX --> FS[fitScale = available / naturalWrapperWidth no Math.min cap]

    PT[PreviewToolbar] -->|leftIcon chips| CHP1[Chip: prev / next / zoom-in / zoom-out / reset]
    XLSX[XlsxPreview] -->|active prop| CHP2[Chip per sheet name]
Loading

Reviews (5): Last reviewed commit: "improvement(files): module cleanup — ded..." | Re-trigger Greptile

@greptile-apps

greptile-apps Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR updates the file-viewer feature in two ways: it changes the zoom baseline for PDF and DOCX previews from "cap at natural print size" to "fit-to-width", and it migrates toolbar/tab controls from legacy Button primitives to canonical Chip pills from the emcn library.

  • Fit-to-width previews: PDF_PAGE_MAX_WIDTH and Math.min(1, …) caps are removed from both the PDF and DOCX scale computations, so 100% zoom now fills the container width using pdf.js canvas sizing and CSS zoom respectively.
  • Chip migration: PreviewToolbar page/zoom controls and XLSX sheet tabs now use Chip with leftIcon, active, and aria-label props; the unused cn import is correctly dropped from xlsx-preview.tsx.
  • Audio icon: The 🎵 emoji is replaced with the Lucide Music icon using --text-muted and size-[32px] design-system tokens.

Confidence Score: 4/5

The changes are well-scoped UI improvements with correct component API usage throughout; safe to merge.

All five files have clean, intentional changes. The Chip migrations follow the emcn API correctly. The one thing worth watching is the PDF ResizeObserver: removing the old width cap means pdf.js now re-renders the canvas on every panel resize, whereas before resizes above ~864 px were no-ops for the renderer. This won't cause incorrect behaviour but can feel sluggish on large multi-page PDFs.

apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/pdf-viewer.tsx — the ResizeObserver path now triggers pdf.js canvas repaints on every resize event in wide panels.

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/pdf-viewer.tsx Removes PDF_PAGE_MAX_WIDTH cap so page canvas now renders at full container width; introduces a minor performance concern where panel resizes above the old cap threshold now trigger full pdf.js re-renders on every frame.
apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-toolbar.tsx Button → Chip migration; icon-only and text-only chips are used correctly per the emcn API (leftIcon, active, aria-label all present); spacing and token usage look consistent.
apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/xlsx-preview.tsx Sheet-tab buttons migrated to Chip with active prop; cn import correctly dropped after removal; overflow-x-auto + shrink-0 pattern handles many-sheet workbooks cleanly.
apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/docx-preview.tsx Removes Math.min(1, …) cap on fitScale so DOCX pages upscale to fill wide panels via CSS zoom; intentional fit-to-width change consistent with the PDF update.
apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/file-viewer.tsx Emoji replaced with Lucide Music icon using design-system tokens; clean single-line change with no side effects.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Container ResizeObserver] --> B{containerWidth > 0?}
    B -- yes --> C[pageWidth = containerWidth - 2×padding]
    B -- no --> D[pageWidth = undefined]
    C --> E[ReactPdfPage width=pageWidth]
    E --> F[pdf.js re-renders canvas at new width]
    
    G[User zoom in/out] --> H[applyZoomAt]
    H --> I[wrapper.style.zoom = next]
    I --> J[CSS visual scale only - no canvas re-render]
    
    subgraph DOCX
      K[fitDocxToContainer] --> L[fitScale = available / naturalWrapperWidth]
      L --> M[scale = fitScale × zoom%/100]
      M --> N[wrapper.style.zoom = scale]
    end
Loading

Reviews (2): Last reviewed commit: "improvement(files): fit-width previews a..." | Re-trigger Greptile

With fit-to-width every pageWidth change re-rasterises all page canvases,
so per-tick updates during a panel-divider drag re-rendered the document
continuously. First measurement still applies immediately.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

…diate resize slot

A hidden container reports zero width from the ResizeObserver; treating
that as the initial measurement pushed the real first width onto the
debounce path and delayed initial render.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 8aea876. Configure here.

…docx refits

- Merge the near-identical AudioPreview/VideoPreview into one MediaPreview
  (shared fetch/blob-URL/error/loading path; only the player differs)
- Debounce docx resize refits the same way the PDF preview debounces width
  measurements (the initial fit comes from the render path, not the observer)
- Document the load-bearing buffer copy in pdf-viewer (pdf.js transfers and
  detaches the ArrayBuffer it receives)
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 6a33064. Configure here.

@waleedlatif1 waleedlatif1 merged commit bc92a2c into staging Jun 12, 2026
10 checks passed
@waleedlatif1 waleedlatif1 deleted the feat/file-viewer-experience branch June 12, 2026 18:55
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.

1 participant