Skip to content

Conversation

@niranjan-uma-shankar
Copy link
Contributor

@niranjan-uma-shankar niranjan-uma-shankar commented Aug 2, 2025

Summary

This PR disables the zoom-on-tap behavior for Unsplash images in mobile viewports. Instead of zooming (which doesn't work well on mobile viewports), tapping now reveals the action buttons (e.g. “Insert” and “❤️”), making the interaction more intuitive for touch users.

Why this change?

  • Zooming into an image in small viewports results in awkward aspect ratios.
  • Tapping should surface actionable UI (buttons), not an unhelpful zoom state.
  • On touch devices, hover-only buttons remain interactive even when invisible, resulting in confusing behaviour. For example, tapping the bottom-right corner of an image can trigger the “Insert” action, even though the button isn’t visible when the image first loads.

This fixes #24585.

Behaviour before

Tapping an image:

  • Zooms in without improving clarity
  • Randomly triggers invisible hover-only buttons
  • In tablet screens, no hover actions visible on zoom
Mobile Tablet
Screen.Recording.2025-08-02.at.6.51.29.PM.mov
tbbf1.mov

Behaviour after

This PR handles touch devices and non-touch browser resized windows correctly.

In touch-enabled devices, tapping an image:

  • No longer zooms in
  • Consistently reveals visible action buttons
  • Enables predictable interactions
Mobile Tablet
aft1.mov
Screen.Recording.2025-08-02.at.8.02.15.PM.mov

In non-touch devices, for example a desktop browser resized to a small viewport:

  • The tap-to-zoom behaviour is retained up to a max-width of 540px.
  • If the browser window is resized to a width below 540px, then the tap-to-zoom is disabled. Mouse hover over the images will reveal the action buttons.
res1.mp4

Testing instructions

  1. Open ghost admin on a mobile viewport.
  2. In /posts, create a new post and click on "Add a feature image".
  3. Use Chrome devtools to simulate a mobile. Click on an image in the search result, and verify that it doesn't open the zoomed in content.
  4. Verify that clicking on an image reveals the action buttons, and that each of the action buttons work as expected.
  5. Search for images, and verify that the action buttons work on the search results.
  6. Now use your desktop browser (not mobile simulated) and resize your browser window to smaller viewports. As you resize, verify that the mouse hover action reveals the action buttons, and clicking on an image zooms in, up to a max-width of 540px. Below 540px width, mouse hover will reveal the action buttons but the images will no longer zoom on click.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 2, 2025

"""

Walkthrough

The GhUnsplashPhoto component was updated by adding a static array OVERLAY_BUTTON_SELECTORS containing CSS selectors for overlay buttons. The zoom action was modified to detect if the device is a touch device or if the viewport width is 540px or less. If either condition is true, zooming is disabled except when clicking on overlay buttons, allowing only those interactions to proceed. For other clicks on touch devices or small viewports, event propagation and default behavior are prevented, effectively disabling zoom. Additionally, a CSS media query was added to change the cursor style from zoom-in to default on .gh-unsplash-photo elements for viewports 540px wide or less.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Assessment against linked issues

Objective Addressed Explanation
Ensure tapping an Unsplash image on mobile performs one clear, consistent action (e.g., disables inconsistent zoom/tap behaviour) (#24585)
Prevent invisible action buttons from being interactive on mobile/touch devices (#24585)
Only allow overlay button interactions to remain functional on touch devices (#24585)

Assessment against linked issues: Out-of-scope changes

No out-of-scope changes were found.
"""

Note

🔌 MCP (Model Context Protocol) integration is now available in Early Access!

Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
ghost/admin/app/components/gh-unsplash-photo.js (1)

58-70: Excellent implementation of touch-specific zoom behavior!

The logic correctly addresses the PR objectives by:

  • Allowing overlay button interactions on touch devices (lines 62-64)
  • Disabling zoom for all other touch interactions (lines 66-70)
  • Preserving existing desktop behavior

The use of closest() to detect overlay button clicks is appropriate and the event handling is correct.

Consider extracting the overlay button selectors to constants for better maintainability:

+    // Overlay button selectors for touch device handling
+    static OVERLAY_BUTTON_SELECTORS = [
+        '.gh-unsplash-button-likes',
+        '.gh-unsplash-button-download',
+        '.gh-unsplash-photo-author'
+    ];
+
     @action
     zoom(event) {
         const {target} = event;
-        const isOverlayButtonClick = target.closest('.gh-unsplash-button-likes') || 
-                                   target.closest('.gh-unsplash-button-download') ||
-                                   target.closest('.gh-unsplash-photo-author');
+        const isOverlayButtonClick = GhUnsplashPhoto.OVERLAY_BUTTON_SELECTORS
+            .some(selector => target.closest(selector));
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b5dedb0 and 45c8a89.

📒 Files selected for processing (1)
  • ghost/admin/app/components/gh-unsplash-photo.js (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Admin tests - Chrome
  • GitHub Check: E2E tests
🔇 Additional comments (1)
ghost/admin/app/components/gh-unsplash-photo.js (1)

44-46: LGTM! Touch device detection implementation is correct.

The use of (pointer: coarse) media query is the standard and reliable way to detect touch devices. The getter pattern ensures reactive evaluation when accessed.

@ErisDS
Copy link
Member

ErisDS commented Aug 4, 2025

Hi @niranjan-uma-shankar thanks for all your bug reports and fixes 🙏
Our team are currently in code freeze whilst we're shipping 6.0. I'd really appreciate if you'd hold off raising any more until we can clear the current backlog, to avoid overwhelming the team. Thanks!

@niranjan-uma-shankar
Copy link
Contributor Author

Noted, I'll hold off as you suggested. Thank you for informing :)

@niranjan-uma-shankar
Copy link
Contributor Author

I'd really appreciate if you'd hold off raising any more until we can clear the current backlog, to avoid overwhelming the team

@ErisDS I implemented a couple more PRs to fix some bugs but kept them in draft mode specifically to avoid adding to the active queue. If it’s better to avoid opening even drafts for now, I can close them and re-open later. Let me know what works best for the team, thanks!

@kevinansfield
Copy link
Member

kevinansfield commented Aug 7, 2025

@niranjan-uma-shankar I haven't fully reviewed yet but the premise of the change sounds great! We have two different Unsplash selector components currently, with a different React based component used for images inside the editor and the publication cover image in settings area, do you see a similar problem with mobile/tablet usage there?

Zooming on Unsplash images in mobile and tablet devices leads to an awkward UI, not compatible with small screens. This removes the zoom capability on mobile and tablet devices.
Overlay button clicks are allowd to pass through on mobile devices
Ref TryGhost#24585
When the browser window on a desktop is resized to a small viewport, this fix ensures that the zoom behaviour is disabled. Zoom continues to work in tab viewports in non-touch devices.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
ghost/admin/app/styles/components/unsplash.css (1)

134-139: Broaden targeting to touch devices to avoid cursor/behavior mismatch on tablets and touch laptops

Width-only targeting can still show a zoom-in cursor on larger touch devices where JS disables zoom. Include a pointer-capability query so the visual affordance matches behavior on touch.

-@media (max-width: 540px) {
+@media (max-width: 540px), (hover: none) and (pointer: coarse) {
     .gh-unsplash-photo {
         cursor: default;
     }
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a3a460f and 8ce814b.

📒 Files selected for processing (2)
  • ghost/admin/app/components/gh-unsplash-photo.js (2 hunks)
  • ghost/admin/app/styles/components/unsplash.css (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • ghost/admin/app/components/gh-unsplash-photo.js
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Setup
🔇 Additional comments (2)
ghost/admin/app/styles/components/unsplash.css (2)

134-139: Specificity check: safe against zoom overlay styles

The new rule won’t override .gh-unsplash-zoom .gh-unsplash-photo { cursor: zoom-out; } due to lower specificity, which is correct. Good addition to align visuals with the updated interaction model.


134-139: Confirm 540px breakpoint aligns with existing breakpoints
I scanned all @media (max-width: …px) usages across the codebase and found common values at 300px, 400px, 440–460px, 500px, 520px, 550px and 600px—but 540px appears only in this component. If our design system’s “mobile” cutoff is 576px (or 550px), we should update it; otherwise please confirm that 540px is the intended threshold.

• ghost/admin/app/styles/components/unsplash.css: lines 134–139

@niranjan-uma-shankar
Copy link
Contributor Author

niranjan-uma-shankar commented Aug 11, 2025

We have two different Unsplash selector components currently, with a different React based component used for images inside the editor and the publication cover image in settings area, do you see a similar problem with mobile/tablet usage there?

@kevinansfield Thanks for bringing this up. I reviewed the behaviour of the React-based Unsplash modal, which is used in the lexical editor and in "Publication cover" modal in /settings/design/edit, and came across a few bugs:

Note:

My recent PRs are functionally complete but currently in draft mode, per this request to avoid overwhelming the review queue. I’m happy to mark them “Ready for review” as soon as I get the go-ahead.

@kevinansfield
Copy link
Member

@niranjan-uma-shankar feel free to move those PRs into ready-to-review, we're out of the 6.0 code freeze period now 🙂

@niranjan-uma-shankar
Copy link
Contributor Author

Hi @kevinansfield 👋 just circling back on this one. It would be great to get some eyes on this PR, along with the other related Unsplash search ones:

Happy to make any adjustments if needed, just let me know!

@ErisDS ErisDS added the community [triage] Community features and bugs label Sep 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community [triage] Community features and bugs needs:review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🐛 Unpredictable tap behaviour on Unsplash search results in mobile viewports

3 participants