components+hooks: refactor window measurement

We relocated window measurment logic into a hook, useGridSpans(), which
tells us the appropriate number of columns for the IconGrid. This is
useful for rendering an InfoPanel in the right place! In future we
should look into a custom implementation using ResizeObserver and
polyfills, and that may be extensible for other use-cases.
This commit is contained in:
rektdeckard
2020-09-24 19:24:00 -04:00
parent 628667c719
commit 22f066c6a9
4 changed files with 17 additions and 8 deletions

View File

@@ -1,7 +1,6 @@
import React, { useRef, useEffect } from "react"; import React, { useRef, useEffect } from "react";
import { useRecoilValue } from "recoil"; import { useRecoilValue } from "recoil";
import { motion, useAnimation } from "framer-motion"; import { motion, useAnimation } from "framer-motion";
import { useWindowSize } from "react-use";
import { IconContext } from "phosphor-react"; import { IconContext } from "phosphor-react";
import { iconWeightAtom, iconSizeAtom, iconColorAtom } from "../../state/atoms"; import { iconWeightAtom, iconSizeAtom, iconColorAtom } from "../../state/atoms";
@@ -9,6 +8,7 @@ import {
filteredQueryResultsSelector, filteredQueryResultsSelector,
isDarkThemeSelector, isDarkThemeSelector,
} from "../../state/selectors"; } from "../../state/selectors";
import useGridSpans from "../../hooks/useGridSpans";
import IconGridItem from "./IconGridItem"; import IconGridItem from "./IconGridItem";
import Warn from "../Warn/Warn"; import Warn from "../Warn/Warn";
import "./IconGrid.css"; import "./IconGrid.css";
@@ -20,9 +20,7 @@ const IconGrid: React.FC<IconGridProps> = () => {
const size = useRecoilValue(iconSizeAtom); const size = useRecoilValue(iconSizeAtom);
const color = useRecoilValue(iconColorAtom); const color = useRecoilValue(iconColorAtom);
const isDark = useRecoilValue(isDarkThemeSelector); const isDark = useRecoilValue(isDarkThemeSelector);
const spans = useGridSpans();
const { width } = useWindowSize();
const spans = Math.floor(Math.min(width - 32, 1120) / 168);
const filteredQueryResults = useRecoilValue(filteredQueryResultsSelector); const filteredQueryResults = useRecoilValue(filteredQueryResultsSelector);

View File

@@ -79,7 +79,6 @@ const IconGridItem: React.FC<IconGridItemProps> = (props) => {
backgroundColor: isOpen ? "rgba(163, 159, 171, 0.1)" : undefined, backgroundColor: isOpen ? "rgba(163, 159, 171, 0.1)" : undefined,
}} }}
custom={delayRef} custom={delayRef}
// whileTap={whileTap}
transition={transition} transition={transition}
variants={itemVariants} variants={itemVariants}
onKeyPress={(e) => e.key === "Enter" && handleOpen()} onKeyPress={(e) => e.key === "Enter" && handleOpen()}

View File

@@ -63,8 +63,7 @@ const InfoPanel: React.FC<InfoPanelProps> = (props) => {
event.currentTarget.blur(); event.currentTarget.blur();
setCopied(type); setCopied(type);
const data = snippets[type]; const data = snippets[type];
// if (!navigator.clipboard) throw new Error("no clipboard!"); data && void navigator.clipboard?.writeText(data);
data && void(navigator.clipboard?.writeText(data));
}; };
const handleDownloadSVG = ( const handleDownloadSVG = (
@@ -81,7 +80,7 @@ const InfoPanel: React.FC<InfoPanelProps> = (props) => {
) => { ) => {
event.currentTarget.blur(); event.currentTarget.blur();
setCopied("svg"); setCopied("svg");
ref.current && void(navigator.clipboard?.writeText(ref.current.outerHTML)); ref.current && void navigator.clipboard?.writeText(ref.current.outerHTML);
}; };
return ( return (

13
src/hooks/useGridSpans.ts Normal file
View File

@@ -0,0 +1,13 @@
import { useWindowSize } from "react-use";
const GRID_PADDING = 32; // .grid-container { padding }
const TOOLBAR_WIDTH = 17; // IS THIS BROWSER-SPECIFIC?
const MAX_GRID_WIDTH = 1120; // .grid { max-width }
const ITEM_WIDTH = 168; // .grid-item { width; height; margin }
export default (): number => {
const { width } = useWindowSize();
return Math.floor(
Math.min(width - GRID_PADDING - TOOLBAR_WIDTH, MAX_GRID_WIDTH) / ITEM_WIDTH
);
};