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:
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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()}
|
||||||
|
|||||||
@@ -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
13
src/hooks/useGridSpans.ts
Normal 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
|
||||||
|
);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user