react-native-menu / menu

UIMenu Component for React Native
MIT License
989 stars 58 forks source link

Clicking on background to Close triggers the press event of the pressed area #853

Open mabdurrafey-afl opened 4 months ago

zollipaul commented 3 months ago

+1 here. workaround for me is to track, if menu is open somehow and then disable all other elements or put an absolute view over the rest to block the touch event. not a good solution though. Someone has other ideas? Is this a bug report or feature request?

mabdurrafey-afl commented 3 months ago

@zollipaul this is a big issue, leading to thoughts to replace this package :-(

fbeccaceci commented 3 months ago

I wrapped the component this way


import { useState } from "react";
import { Pressable, ViewStyle, View, Dimensions } from "react-native";
import { MenuView, MenuComponentProps } from "@react-native-menu/menu";
import { Portal } from "@gorhom/portal";

export type MenuProps = MenuComponentProps;

export default function Menu({ children, ...props }: MenuProps) {
  const [isOpen, setIsOpen] = useState(false);

  const onPressAction: MenuComponentProps["onPressAction"] = ({ nativeEvent }) => {
    setIsOpen(false);
    props.onPressAction?.({ nativeEvent });
  };

  return (
    <MenuView {...props} onPressAction={onPressAction}>
      <Pressable onPress={() => setIsOpen(true)}>{children}</Pressable>
      <Portal>
        {isOpen && <Pressable style={absoluteViewStyle} onPress={() => setIsOpen(false)} />}
      </Portal>
    </MenuView>
  );
}

const screenSize = Dimensions.get("screen");

const absoluteViewStyle: ViewStyle = {
  position: "absolute",
  top: 0,
  left: 0,
  width: screenSize.width,
  height: screenSize.height,

  zIndex: 999,
};

And it makes it work more as you would expect, at least on ios, haven't tried it on android

timmytan18 commented 1 day ago

I wrapped the component this way

import { useState } from "react";
import { Pressable, ViewStyle, View, Dimensions } from "react-native";
import { MenuView, MenuComponentProps } from "@react-native-menu/menu";
import { Portal } from "@gorhom/portal";

export type MenuProps = MenuComponentProps;

export default function Menu({ children, ...props }: MenuProps) {
  const [isOpen, setIsOpen] = useState(false);

  const onPressAction: MenuComponentProps["onPressAction"] = ({ nativeEvent }) => {
    setIsOpen(false);
    props.onPressAction?.({ nativeEvent });
  };

  return (
    <MenuView {...props} onPressAction={onPressAction}>
      <Pressable onPress={() => setIsOpen(true)}>{children}</Pressable>
      <Portal>
        {isOpen && <Pressable style={absoluteViewStyle} onPress={() => setIsOpen(false)} />}
      </Portal>
    </MenuView>
  );
}

const screenSize = Dimensions.get("screen");

const absoluteViewStyle: ViewStyle = {
  position: "absolute",
  top: 0,
  left: 0,
  width: screenSize.width,
  height: screenSize.height,

  zIndex: 999,
};

And it makes it work more as you would expect, at least on ios, haven't tried it on android

Adding on to this, using onPressIn for the inner Pressable makes it faster