portail-associations/client/src/hooks/useMobile.tsx

83 lines
2.3 KiB
TypeScript

import * as React from "react";
const MOBILE_BREAKPOINT = 768;
const TABLET_BREAKPOINT = 1280;
export function useIsMobile() {
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(
undefined
);
React.useEffect(() => {
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
const onChange = () => {
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
};
mql.addEventListener("change", onChange);
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
return () => mql.removeEventListener("change", onChange);
}, []);
return !!isMobile;
}
export type ViewportDevice = "mobile" | "tablet" | "desktop";
export function useViewportDevice(): ViewportDevice {
const [device, setDevice] = React.useState<ViewportDevice>("desktop");
React.useEffect(() => {
const updateDevice = () => {
const width = window.innerWidth;
if (width < MOBILE_BREAKPOINT) {
setDevice("mobile");
return;
}
if (width < TABLET_BREAKPOINT) {
setDevice("tablet");
return;
}
setDevice("desktop");
};
updateDevice();
window.addEventListener("resize", updateDevice);
return () => window.removeEventListener("resize", updateDevice);
}, []);
return device;
}
export function useViewportFlags() {
const device = useViewportDevice();
const [isTouchLike, setIsTouchLike] = React.useState(false);
const [prefersReducedMotion, setPrefersReducedMotion] = React.useState(false);
React.useEffect(() => {
const pointerMedia = window.matchMedia("(pointer: coarse)");
const motionMedia = window.matchMedia("(prefers-reduced-motion: reduce)");
const updateFlags = () => {
setIsTouchLike(pointerMedia.matches || navigator.maxTouchPoints > 0);
setPrefersReducedMotion(motionMedia.matches);
};
updateFlags();
pointerMedia.addEventListener("change", updateFlags);
motionMedia.addEventListener("change", updateFlags);
return () => {
pointerMedia.removeEventListener("change", updateFlags);
motionMedia.removeEventListener("change", updateFlags);
};
}, []);
return {
device,
isMobile: device === "mobile",
isTablet: device === "tablet",
isDesktop: device === "desktop",
isTouchLike,
prefersReducedMotion,
};
}