Skip to content

Instantly share code, notes, and snippets.

@PinkiNice
Last active March 7, 2024 14:31
Show Gist options
  • Save PinkiNice/596ac733614bbd90eecb0593dccdee08 to your computer and use it in GitHub Desktop.
Save PinkiNice/596ac733614bbd90eecb0593dccdee08 to your computer and use it in GitHub Desktop.
Media Queries for CSS-in-JS + Rect
import { CSSPropertiesWithMultiValues } from '@emotion/serialize';
import React, { PropsWithChildren, useEffect, useState } from 'react';
type ScreenSize = 'xs' | 'sm' | 'md' | 'lg';
const screenSize = {
xs: 0,
sm: 576,
md: 768,
lg: 992,
};
type MediaQueryTarget = { min?: ScreenSize; max?: ScreenSize } | ScreenSize;
function buildMediaQueryString(size: MediaQueryTarget) {
const min = typeof size === 'string' ? size : size.min;
const max = typeof size === 'string' ? null : size.max;
const maxStatement = max ? `(max-width: ${screenSize[max]}px)` : '';
const minStatement = min ? `(min-width: ${screenSize[min]}px)` : '';
const combined = [minStatement, maxStatement].filter(Boolean).join(' and ');
return combined;
}
/**
*
* @param size mobile-first size or object with min and max sizes
* @param css styles to be applied when condition is met
* @returns
*/
export function media(
size: MediaQueryTarget,
css: CSSPropertiesWithMultiValues | { [key: string]: any }
) {
const mediaQueryExpression = buildMediaQueryString(size);
return {
[`@media ${mediaQueryExpression}`]: {
...css,
},
};
}
export function useMediaQuery(size: MediaQueryTarget) {
const [matches, setMatches] = useState(false);
useEffect(() => {
const mediaQuery = window.matchMedia(buildMediaQueryString(size));
setMatches(mediaQuery.matches);
const listener = () => {
setMatches(mediaQuery.matches);
};
mediaQuery.addEventListener('change', listener);
return () => {
mediaQuery.removeEventListener('change', listener);
};
}, [size]);
return matches;
}
export const MediaQuery = ({
min,
children,
}: PropsWithChildren<{ min: ScreenSize }>) => {
const matches = useMediaQuery(min);
if (matches) {
return <React.Fragment>{children}</React.Fragment>;
}
return null;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment