Skip to content

feat(components): Add getObjectUrl() prop to InputFile#3139

Open
edison-cy-yang wants to merge 3 commits into
masterfrom
JOB-163813-input-file-src-for-non-image-files-cannot-be-previewed
Open

feat(components): Add getObjectUrl() prop to InputFile#3139
edison-cy-yang wants to merge 3 commits into
masterfrom
JOB-163813-input-file-src-for-non-image-files-cannot-be-previewed

Conversation

@edison-cy-yang
Copy link
Copy Markdown
Contributor

@edison-cy-yang edison-cy-yang commented May 7, 2026

Why Is This Changing?

  • FileUpload.src() returns a data: URL, which browsers block from top-frame navigation (window.open, <a target="_blank">) for security reasons.
  • This breaks "open in new tab" previews for non-image attachments (PDFs, Word docs, etc.) produced by <InputFile>.
  • The most visible symptom is in <Gallery>: clicking a non-image thumbnail silently fails with Not allowed to navigate top frame to data URL.
  • Consumers currently work around this by wrapping src() and substituting a different URL — the fix belongs in the design system.

What Is Changing?

  • New method FileUpload.getObjectUrl() returns { url: string; revoke: () => void } — a navigation-safe blob: URL paired with its cleanup function.
  • <Gallery> uses it internally on the non-image thumbnail click path; revoke is scheduled via requestAnimationFrame after window.open.
  • src() is unchanged. New code should prefer getObjectUrl(); moving away from the src() pattern over time without formally deprecating it.
  • Docs updated in InputFileNotes.mdx and Gallery.stories.mdx.

Consumer Impact

  • Impact: Low

  • Action required: None — additive change. Opt into getObjectUrl() when navigation is needed.

  • Breaking change: No

  • Existing src() callers continue to work.

  • getObjectUrl is optional on FileUpload — external consumers constructing FileUpload-shaped objects don't need to provide it.

  • GalleryFile picks getObjectUrl from FileUpload (non-breaking TS change).

  • <Gallery> consumers passing FileUpload directly now get working non-image previews — fix, not regression.

Validation

  • New unit tests in InputFile.test.tsx and Gallery.test.tsx.
  • All existing InputFile and Gallery tests pass unchanged (51 tests, 5 snapshots).
  • New Storybook story Gallery > With InputFile demonstrates the full flow.
  • Manual QA: PDF thumbnail → opens in new tab; image thumbnail → LightBox.

Reviewer Notes

  • API shape: { url, revoke } returned together vs. separate sibling methods on FileUpload. Coupled-return prevents getting the URL without seeing the cleanup handle.
  • Optionality: getObjectUrl? is optional so external consumers / mocks aren't forced to implement it. Always present on <InputFile>-produced objects.
  • GalleryFile Pick: extends the existing Pick<FileUpload, ...> instead of redeclaring, so JSDoc and shape stay in sync.
  • requestAnimationFrame(revoke) timing: gives the new tab a frame to start loading before the URL is invalidated. Revoking too early = blank tab; not revoking = leaks until page unload.

Changes can be tested via Pre-release.


In Atlantis we use Github's built in pull request reviews.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

Deploying atlantis with  Cloudflare Pages  Cloudflare Pages

Latest commit: 14f3dc5
Status: ✅  Deploy successful!
Preview URL: https://96979483.atlantis.pages.dev
Branch Preview URL: https://job-163813-input-file-src-fo.atlantis.pages.dev

View logs

@edison-cy-yang edison-cy-yang marked this pull request as ready for review May 11, 2026 18:53
@edison-cy-yang edison-cy-yang requested a review from a team as a code owner May 11, 2026 18:53
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 11, 2026

Published Pre-release for 14f3dc5 with versions:

  - @jobber/components@7.10.1-JOB-163813-14f3dc5.2+14f3dc56f
  - @jobber/components-native@0.101.9-JOB-163813-14f3dc5.9+14f3dc56f
  - @jobber/design@0.99.1-JOB-163813-14f3dc5.18+14f3dc56f
  - @jobber/eslint-config@0.14.1-JOB-163813-14f3dc5.41+14f3dc56f
  - @jobber/formatters@0.5.1-JOB-163813-14f3dc5.414+14f3dc56f
  - @jobber/generators@0.12.7-JOB-163813-14f3dc5.147+14f3dc56f
  - @jobber/hooks@2.19.5-JOB-163813-14f3dc5.41+14f3dc56f
  - @jobber/stylelint-config@0.7.4-JOB-163813-14f3dc5.41+14f3dc56f

To install the new version(s) for Web run:

pnpm add @jobber/components@7.10.1-JOB-163813-14f3dc5.2+14f3dc56f @jobber/design@0.99.1-JOB-163813-14f3dc5.18+14f3dc56f @jobber/eslint-config@0.14.1-JOB-163813-14f3dc5.41+14f3dc56f @jobber/formatters@0.5.1-JOB-163813-14f3dc5.414+14f3dc56f @jobber/generators@0.12.7-JOB-163813-14f3dc5.147+14f3dc56f @jobber/hooks@2.19.5-JOB-163813-14f3dc5.41+14f3dc56f @jobber/stylelint-config@0.7.4-JOB-163813-14f3dc5.41+14f3dc56f

To install the new version(s) for Mobile run:

pnpm add @jobber/components-native@0.101.9-JOB-163813-14f3dc5.9+14f3dc56f @jobber/design@0.99.1-JOB-163813-14f3dc5.18+14f3dc56f @jobber/eslint-config@0.14.1-JOB-163813-14f3dc5.41+14f3dc56f @jobber/formatters@0.5.1-JOB-163813-14f3dc5.414+14f3dc56f @jobber/generators@0.12.7-JOB-163813-14f3dc5.147+14f3dc56f @jobber/hooks@2.19.5-JOB-163813-14f3dc5.41+14f3dc56f @jobber/stylelint-config@0.7.4-JOB-163813-14f3dc5.41+14f3dc56f

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant