55 lines
1.3 KiB
TypeScript
55 lines
1.3 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
|
|
export default function useMediaQuery(query: string): boolean {
|
|
const getMatches = (query: string): boolean => {
|
|
// Prevents SSR issues
|
|
if (typeof window !== "undefined") {
|
|
return window.matchMedia(query).matches;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
const [matches, setMatches] = useState<boolean>(getMatches(query));
|
|
|
|
function handleChange() {
|
|
setMatches(getMatches(query));
|
|
}
|
|
|
|
useEffect(() => {
|
|
const matchMedia = window.matchMedia(query);
|
|
|
|
// Triggered at the first client-side load and if query changes
|
|
handleChange();
|
|
|
|
// Listen matchMedia
|
|
matchMedia.addEventListener("change", handleChange);
|
|
|
|
return () => {
|
|
matchMedia.removeEventListener("change", handleChange);
|
|
};
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [query]);
|
|
|
|
return matches;
|
|
}
|
|
|
|
export function useMediaThin() {
|
|
return useMediaQuery("(max-width: 25rem)");
|
|
}
|
|
|
|
export function useMediaMobile() {
|
|
return useMediaQuery("(max-width: 60rem)");
|
|
}
|
|
|
|
export function useMediaDesktop() {
|
|
return useMediaQuery("(min-width: 60rem)");
|
|
}
|
|
|
|
export function useMediaCoarse() {
|
|
return useMediaQuery("(pointer: coarse)");
|
|
}
|
|
|
|
export function useMediaFine() {
|
|
return useMediaQuery("(pointer: fine)");
|
|
}
|