Allow to zoom image on mobile if relevant (#3364)

This commit is contained in:
Greg Bergé
2025-06-20 10:25:58 +02:00
committed by GitHub
parent 42d43e09c4
commit caaa692f0b
2 changed files with 10 additions and 23 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Allow to zoom images on mobile if relevant
@@ -9,6 +9,8 @@ import { tcls } from '@/lib/tailwind';
import styles from './ZoomImage.module.css';
const PADDING = 32; // Padding around the image in the modal, in pixels
/**
* Replacement for an <img> tag that allows zooming.
* The implementation uses the experimental View Transition API in Chrome for a smooth transition.
@@ -28,14 +30,9 @@ export function ZoomImage(
// Only allow zooming when image will not actually be larger and on mobile
React.useEffect(() => {
if (isTouchDevice()) {
return;
}
const imageWidth = typeof width === 'number' ? width : 0;
let viewWidth = 0;
const mediaQueryList = window.matchMedia('(min-width: 768px)');
const resizeObserver =
typeof ResizeObserver !== 'undefined'
? new ResizeObserver((entries) => {
@@ -52,8 +49,9 @@ export function ZoomImage(
: null;
const onChange = () => {
if (!mediaQueryList.matches) {
// Don't allow zooming on mobile
const viewInModalWidth = window.innerWidth - PADDING * 2;
if (viewWidth >= viewInModalWidth) {
// If the image will be smaller or same size as it is in the modal, disable zooming
setZoomable(false);
} else if (resizeObserver && imageWidth && viewWidth && imageWidth <= viewWidth) {
// Image can't be zoomed if it's already rendered as it's largest size
@@ -63,10 +61,6 @@ export function ZoomImage(
}
};
if ('addEventListener' in mediaQueryList) {
mediaQueryList.addEventListener('change', onChange);
}
if (imgRef.current) {
resizeObserver?.observe(imgRef.current);
}
@@ -78,9 +72,6 @@ export function ZoomImage(
return () => {
resizeObserver?.disconnect();
if ('removeEventListener' in mediaQueryList) {
mediaQueryList.removeEventListener('change', onChange);
}
};
}, [imgRef, width]);
@@ -290,12 +281,3 @@ function startViewTransition(callback: () => void, onEnd?: () => void) {
onEnd?.();
}
}
function isTouchDevice(): boolean {
return (
'ontouchstart' in window ||
navigator.maxTouchPoints > 0 ||
// @ts-ignore
navigator.msMaxTouchPoints > 0
);
}