mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-22 22:49:45 +01:00
fix: correct submenu positioning
This commit is contained in:
@@ -10,6 +10,7 @@ import React, {
|
||||
import { Flex, Box, Text, Button } from "rebass";
|
||||
import useMobile from "../../utils/use-mobile";
|
||||
import { AnimatedFlex } from "../animated";
|
||||
import { getPosition } from "../../hooks/use-menu";
|
||||
|
||||
function useMenuFocus(items) {
|
||||
const [focusIndex, setFocusIndex] = useState(-1);
|
||||
@@ -121,8 +122,7 @@ function MenuContainer({ title, children }) {
|
||||
borderRadius: "default",
|
||||
boxShadow: "0px 0px 10px 0px #00000022",
|
||||
border: "1px solid var(--border)",
|
||||
minWidth: 200,
|
||||
maxWidth: 500,
|
||||
width: 220,
|
||||
}}
|
||||
>
|
||||
{title && (
|
||||
@@ -217,16 +217,35 @@ function MenuItem({ item, data, isFocused, isSubmenuOpen, onClose, onHover }) {
|
||||
isPremium,
|
||||
} = item;
|
||||
const itemRef = useRef();
|
||||
const subMenuRef = useRef();
|
||||
|
||||
useEffect(() => {
|
||||
if (isFocused) itemRef.current?.focus();
|
||||
}, [isFocused]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!subMenuRef.current) return;
|
||||
if (!isSubmenuOpen) {
|
||||
subMenuRef.current.style.visibility = "hidden";
|
||||
return;
|
||||
}
|
||||
|
||||
const { top, left } = getPosition(
|
||||
subMenuRef.current,
|
||||
itemRef.current,
|
||||
"right"
|
||||
);
|
||||
|
||||
subMenuRef.current.style.visibility = "visible";
|
||||
subMenuRef.current.style.top = `${top}px`;
|
||||
subMenuRef.current.style.left = `${left}px`;
|
||||
}, [isSubmenuOpen]);
|
||||
|
||||
const onAction = useCallback(
|
||||
(e) => {
|
||||
e.stopPropagation();
|
||||
if (onClose) onClose();
|
||||
onClick(data, item);
|
||||
if (onClick) onClick(data, item);
|
||||
},
|
||||
[onClick, onClose, item, data]
|
||||
);
|
||||
@@ -249,7 +268,7 @@ function MenuItem({ item, data, isFocused, isSubmenuOpen, onClose, onHover }) {
|
||||
as="li"
|
||||
flexDirection={"column"}
|
||||
flex={1}
|
||||
sx={{ position: "relative" }}
|
||||
// sx={{ position: "relative" }}
|
||||
onMouseOver={onHover}
|
||||
>
|
||||
<Button
|
||||
@@ -290,12 +309,14 @@ function MenuItem({ item, data, isFocused, isSubmenuOpen, onClose, onHover }) {
|
||||
{hasSubmenu && <ChevronRight size={14} />}
|
||||
</Flex>
|
||||
</Button>
|
||||
{hasSubmenu && isSubmenuOpen && (
|
||||
{hasSubmenu && (
|
||||
<Flex
|
||||
ref={subMenuRef}
|
||||
style={{ visibility: "hidden" }}
|
||||
sx={{
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: itemRef.current?.offsetWidth,
|
||||
// top: 0,
|
||||
// left: itemRef.current?.offsetWidth,
|
||||
}}
|
||||
>
|
||||
<Menu
|
||||
|
||||
@@ -46,28 +46,32 @@ export function useMenu() {
|
||||
* @returns
|
||||
*/
|
||||
export function getPosition(element, relativeTo = "mouse", location) {
|
||||
const { x, y, width, height } =
|
||||
const { x, y, width, height, actualX, actualY } =
|
||||
relativeTo === "mouse" ? mousePosition : getElementPosition(relativeTo);
|
||||
|
||||
const elementWidth = element.offsetWidth;
|
||||
const elementHeight = element.offsetHeight;
|
||||
|
||||
const windowWidth = window.document.body.offsetWidth;
|
||||
const windowHeight = window.document.body.offsetHeight;
|
||||
const windowWidth = window.innerHeight;
|
||||
const windowHeight = window.innerHeight - 50;
|
||||
|
||||
let position = { top: undefined, left: undefined };
|
||||
|
||||
if (windowWidth - x < elementWidth) {
|
||||
if (windowWidth - actualX < elementWidth) {
|
||||
const xDiff = actualX - x;
|
||||
position.left = windowWidth - elementWidth;
|
||||
position.left -= xDiff;
|
||||
} else {
|
||||
position.left = x;
|
||||
|
||||
if (location === "right") position.top += width;
|
||||
else if (location === "left") position.top -= width;
|
||||
if (location === "right") position.left += width;
|
||||
else if (location === "left") position.left -= width;
|
||||
}
|
||||
|
||||
if (windowHeight - y < elementHeight) {
|
||||
if (windowHeight - actualY < elementHeight) {
|
||||
const yDiff = actualY - y;
|
||||
position.top = windowHeight - elementHeight;
|
||||
position.top -= yDiff;
|
||||
} else {
|
||||
position.top = y;
|
||||
if (location === "below") position.top += height;
|
||||
@@ -98,6 +102,8 @@ function getMousePosition(e) {
|
||||
return {
|
||||
x: posx,
|
||||
y: posy,
|
||||
actualY: posy,
|
||||
actualX: posx,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -106,11 +112,14 @@ function getMousePosition(e) {
|
||||
* @param {HTMLElement} element
|
||||
*/
|
||||
function getElementPosition(element) {
|
||||
const rect = element.getBoundingClientRect();
|
||||
return {
|
||||
x: element.offsetLeft,
|
||||
y: element.offsetTop,
|
||||
width: element.offsetWidth,
|
||||
height: element.offsetHeight,
|
||||
actualY: rect.y,
|
||||
actualX: rect.x,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -167,7 +176,7 @@ function mapMenuItems(items, data) {
|
||||
color,
|
||||
iconColor,
|
||||
|
||||
items,
|
||||
items: hasSubmenu ? mapMenuItems(items, data) : [],
|
||||
};
|
||||
|
||||
prev.push(menuItem);
|
||||
|
||||
Reference in New Issue
Block a user