Refactored token menu overlay into two components

This commit is contained in:
Mitchell McCaffrey 2020-04-20 10:56:51 +10:00
parent ef369f4866
commit 27d3903e66
2 changed files with 77 additions and 36 deletions

69
src/components/MapMenu.js Normal file
View File

@ -0,0 +1,69 @@
import React from "react";
import Modal from "react-modal";
function MapMenu({
isOpen,
onRequestClose,
onModalContent,
top,
left,
bottom,
right,
children,
}) {
function handleModalContent(node) {
if (node) {
// Close modal if interacting with any other element
function handlePointerDown(event) {
const path = event.composedPath();
if (!path.includes(node)) {
onRequestClose();
document.body.removeEventListener("pointerdown", handlePointerDown);
}
}
document.body.addEventListener("pointerdown", handlePointerDown);
// Check for wheel event to close modal as well
document.body.addEventListener(
"wheel",
() => {
onRequestClose();
},
{ once: true }
);
}
onModalContent(node);
}
return (
<Modal
isOpen={isOpen}
onRequestClose={onRequestClose}
style={{
overlay: { top: "0", bottom: "initial" },
content: {
backgroundColor: "hsla(230, 25%, 18%, 0.8)",
top,
left,
right,
bottom,
padding: 0,
borderRadius: "4px",
border: "none",
},
}}
contentRef={handleModalContent}
>
{children}
</Modal>
);
}
MapMenu.defaultProps = {
onModalContent: () => {},
top: "initial",
left: "initial",
right: "initial",
bottom: "initial",
};
export default MapMenu;

View File

@ -1,8 +1,9 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import Modal from "react-modal";
import interact from "interactjs"; import interact from "interactjs";
import { Box, Input } from "theme-ui"; import { Box, Input } from "theme-ui";
import MapMenu from "./MapMenu";
import colors, { colorOptions } from "../helpers/colors"; import colors, { colorOptions } from "../helpers/colors";
function TokenMenu({ tokenClassName, onTokenChange }) { function TokenMenu({ tokenClassName, onTokenChange }) {
@ -85,29 +86,11 @@ function TokenMenu({ tokenClassName, onTokenChange }) {
function handleModalContent(node) { function handleModalContent(node) {
if (node) { if (node) {
// Focus input
const tokenLabelInput = node.querySelector("#changeTokenLabel"); const tokenLabelInput = node.querySelector("#changeTokenLabel");
tokenLabelInput.focus(); tokenLabelInput.focus();
tokenLabelInput.setSelectionRange(7, 8); tokenLabelInput.setSelectionRange(7, 8);
// Close modal if interacting with any other element
function handlePointerDown(event) {
const path = event.composedPath();
if (!path.includes(node)) {
setIsOpen(false);
document.body.removeEventListener("pointerdown", handlePointerDown);
}
}
document.body.addEventListener("pointerdown", handlePointerDown);
// Check for wheel event to close modal as well
document.body.addEventListener(
"wheel",
() => {
setIsOpen(false);
},
{ once: true }
);
// Ensure menu is in bounds // Ensure menu is in bounds
const nodeRect = node.getBoundingClientRect(); const nodeRect = node.getBoundingClientRect();
const map = document.querySelector(".map"); const map = document.querySelector(".map");
@ -125,23 +108,12 @@ function TokenMenu({ tokenClassName, onTokenChange }) {
} }
return ( return (
<Modal <MapMenu
isOpen={isOpen} isOpen={isOpen}
onRequestClose={handleRequestClose} onRequestClose={handleRequestClose}
style={{ top={`${menuTop}px`}
overlay: { top: "0", bottom: "initial" }, left={`${menuLeft}px`}
content: { onModalContent={handleModalContent}
backgroundColor: "hsla(230, 25%, 18%, 0.8)",
top: `${menuTop}px`,
left: `${menuLeft}px`,
right: "initial",
bottom: "initial",
padding: 0,
borderRadius: "4px",
border: "none",
},
}}
contentRef={handleModalContent}
> >
<Box sx={{ width: "104px" }} p={1}> <Box sx={{ width: "104px" }} p={1}>
<Box <Box
@ -201,7 +173,7 @@ function TokenMenu({ tokenClassName, onTokenChange }) {
))} ))}
</Box> </Box>
</Box> </Box>
</Modal> </MapMenu>
); );
} }