Simplified menu interaction prevention

This commit is contained in:
Mitchell McCaffrey 2020-05-22 13:46:52 +10:00
parent 6b675d8200
commit 9e01ad1d0e
3 changed files with 33 additions and 27 deletions

View File

@ -163,12 +163,12 @@ function Map({
/>
));
const tokenMenu = isTokenMenuOpen && (
const tokenMenu = (
<TokenMenu
isOpen={isTokenMenuOpen}
onRequestClose={() => setIsTokenMenuOpen(false)}
onTokenChange={onMapTokenStateChange}
tokenState={mapState.tokens[tokenMenuOptions.tokenStateId]}
tokenState={mapState && mapState.tokens[tokenMenuOptions.tokenStateId]}
tokenImage={tokenMenuOptions.tokenImage}
/>
);

View File

@ -4,6 +4,8 @@ import { useThemeUI } from "theme-ui";
import MapInteractionContext from "../../contexts/MapInteractionContext";
import usePrevious from "../../helpers/usePrevious";
function MapMenu({
isOpen,
onRequestClose,
@ -22,7 +24,16 @@ function MapMenu({
// callback
const [modalContentNode, setModalContentNode] = useState(null);
// Toggle map interaction when menu is opened
const wasOpen = usePrevious(isOpen);
const { setPreventMapInteraction } = useContext(MapInteractionContext);
useEffect(() => {
if (isOpen && !wasOpen) {
setPreventMapInteraction(true);
} else if (wasOpen && !isOpen) {
setPreventMapInteraction(false);
}
}, [isOpen, setPreventMapInteraction, wasOpen]);
useEffect(() => {
// Close modal if interacting with any other element
@ -32,31 +43,29 @@ function MapMenu({
!path.includes(modalContentNode) &&
!(excludeNode && path.includes(excludeNode))
) {
setPreventMapInteraction(false);
onRequestClose();
document.body.removeEventListener("pointerdown", handlePointerDown);
}
}
if (modalContentNode) {
setPreventMapInteraction(true);
document.body.addEventListener("pointerdown", handlePointerDown);
// Check for wheel event to close modal as well
document.body.addEventListener(
"wheel",
() => {
setPreventMapInteraction(false);
onRequestClose();
},
{ once: true }
);
}
return () => {
if (modalContentNode) {
document.body.removeEventListener("pointerdown", handlePointerDown);
}
};
}, [modalContentNode, excludeNode, onRequestClose, setPreventMapInteraction]);
}, [modalContentNode, excludeNode, onRequestClose]);
function handleModalContent(node) {
setModalContentNode(node);

View File

@ -1,4 +1,4 @@
import React, { useEffect, useState, useContext } from "react";
import React, { useEffect, useState } from "react";
import { Box, Input, Slider, Flex, Text } from "theme-ui";
import MapMenu from "../map/MapMenu";
@ -7,8 +7,6 @@ import colors, { colorOptions } from "../../helpers/colors";
import usePrevious from "../../helpers/usePrevious";
import MapInteractionContext from "../../contexts/MapInteractionContext";
const defaultTokenMaxSize = 6;
/**
@ -34,7 +32,7 @@ function TokenMenu({
const [tokenMaxSize, setTokenMaxSize] = useState(defaultTokenMaxSize);
useEffect(() => {
if (isOpen && !wasOpen) {
if (isOpen && !wasOpen && tokenState) {
setTokenMaxSize(Math.max(tokenState.size, defaultTokenMaxSize));
}
}, [isOpen, tokenState, wasOpen]);
@ -99,8 +97,6 @@ function TokenMenu({
}
}
const { setPreventMapInteraction } = useContext(MapInteractionContext);
return (
<MapMenu
isOpen={isOpen}
@ -114,7 +110,6 @@ function TokenMenu({
as="form"
onSubmit={(e) => {
e.preventDefault();
setPreventMapInteraction(false);
onRequestClose();
}}
sx={{ alignItems: "center" }}
@ -130,7 +125,7 @@ function TokenMenu({
<Input
id="changeTokenLabel"
onChange={handleLabelChange}
value={tokenState.label}
value={(tokenState && tokenState.label) || ""}
sx={{
padding: "4px",
border: "none",
@ -162,18 +157,20 @@ function TokenMenu({
onClick={() => handleStatusChange(color)}
aria-label={`Token label Color ${color}`}
>
{tokenState.statuses && tokenState.statuses.includes(color) && (
<Box
sx={{
width: "100%",
height: "100%",
border: "2px solid white",
position: "absolute",
top: 0,
borderRadius: "50%",
}}
/>
)}
{tokenState &&
tokenState.statuses &&
tokenState.statuses.includes(color) && (
<Box
sx={{
width: "100%",
height: "100%",
border: "2px solid white",
position: "absolute",
top: 0,
borderRadius: "50%",
}}
/>
)}
</Box>
))}
</Box>
@ -187,7 +184,7 @@ function TokenMenu({
Size:
</Text>
<Slider
value={tokenState.size || 1}
value={(tokenState && tokenState.size) || 1}
onChange={handleSizeChange}
step={1}
min={1}