πŸ“± A performant, easy to use hold to open context menu for React Native powered by Reanimated πŸš€

Overview

React Native Hold Menu

Reanimated v2 version npm npm runs with expo

A performant, easy to use hold to open context menu for React Native powered by Reanimated. πŸ”₯

This package is experimental and still in progress. Using it in production is not preffered yet.


hold-menu-preview

Features

  • Powered with Reanimated v2. πŸš€
  • Smooth interactions & animations.
  • Supports dark/light Mode. 🌚 🌝
  • Supports device orientation change.
  • Compatible with Expo.
  • Written in TypeScript.

Getting Started

Check out the documentation website.


Contributors

License

MIT

Show Your Support

Please give a star if you like this project! 🀩

Comments
  • MenuItem icon should be conditionally rendered

    MenuItem icon should be conditionally rendered

    Describe the bug

    In the expo example, the icons do not render for a couple reasons:

    1. The iconProvider is not added.
    2. The icons are defined as functions instead of strings, I fixed this locally by patching this line:
    {!item.isTitle && item.icon && AnimatedIcon && (
      typeof item.icon === 'string' ? <AnimatedIcon name={item.icon} size={18} style={textColor} /> : item.icon()
    )}
    

    Notice I also conditionally hide the icons if they aren't defined, this isn't great but it does prevent the 'rendering undefined' bug.

    Here is the diff that solved my problem:

    diff --git a/node_modules/react-native-hold-menu/src/components/menu/MenuItem.tsx b/node_modules/react-native-hold-menu/src/components/menu/MenuItem.tsx
    index efa3e73..18674cd 100644
    --- a/node_modules/react-native-hold-menu/src/components/menu/MenuItem.tsx
    +++ b/node_modules/react-native-hold-menu/src/components/menu/MenuItem.tsx
    @@ -64,8 +64,8 @@ const MenuItemComponent = ({ item, isLast }: MenuItemComponentProps) => {
             >
               {item.text}
             </Animated.Text>
    -        {!item.isTitle && item.icon && (
    -          <AnimatedIcon name={item.icon} size={18} style={textColor} />
    +        {!item.isTitle && item.icon && AnimatedIcon && (
    +          typeof item.icon === 'string' ? <AnimatedIcon name={item.icon} size={18} style={textColor} /> : item.icon()
             )}
           </AnimatedTouchable>
           {item.withSeparator && <Separator />}
    diff --git a/node_modules/react-native-hold-menu/src/components/menu/MenuList.tsx b/node_modules/react-native-hold-menu/src/components/menu/MenuList.tsx
    index c476f1d..fb02325 100644
    --- a/node_modules/react-native-hold-menu/src/components/menu/MenuList.tsx
    +++ b/node_modules/react-native-hold-menu/src/components/menu/MenuList.tsx
    @@ -33,7 +33,7 @@ import { useInternal } from '../../hooks';
     import { deepEqual } from '../../utils/validations';
     import { leftOrRight } from './calculations';
     
    -const MenuContainerComponent = IS_IOS ? BlurView : View;
    +const MenuContainerComponent = BlurView;
     const AnimatedView = Animated.createAnimatedComponent<{
       animatedProps: Partial<{ blurType: string }>;
     }>(MenuContainerComponent);
    @@ -72,8 +72,8 @@ const MenuListComponent = () => {
           state.value === CONTEXT_MENU_STATE.ACTIVE
             ? withSpring(1, SPRING_CONFIGURATION_MENU)
             : withTiming(0, {
    -            duration: HOLD_ITEM_TRANSFORM_DURATION,
    -          });
    +          duration: HOLD_ITEM_TRANSFORM_DURATION,
    +        });
     
         const opacityAnimation = () =>
           withTiming(state.value === CONTEXT_MENU_STATE.ACTIVE ? 1 : 0, {
    @@ -104,8 +104,8 @@ const MenuListComponent = () => {
                 ? 'rgba(255, 255, 255, .75)'
                 : 'rgba(255, 255, 255, .95)'
               : IS_IOS
    -          ? 'rgba(0,0,0,0.5)'
    -          : 'rgba(39, 39, 39, .8)',
    +            ? 'rgba(0,0,0,0.5)'
    +            : 'rgba(39, 39, 39, .8)',
         };
       }, [theme]);
     
    @@ -114,6 +114,7 @@ const MenuListComponent = () => {
       }, [theme]);
     
       const setter = (items: MenuItemProps[]) => {
    +    console.log('add items:', items)
         setItemList(items);
         prevList.value = items;
       };
    

    This issue body was partially generated by patch-package.

    Notice dropping the IS_IOS check fixed the blur issue as well.

    bug wip 
    opened by EvanBacon 12
  • feat: add optional haptic feedback

    feat: add optional haptic feedback

    Motivation

    I was hoping to start a discussion about haptic feedback. This library nails down the "pop" for a hold menu wonderfully, but it's hard to not notice that it's missing any sort of haptics. I found that you at one point added expo-haptics in c3e8105a05f229cbc3a25488f9b9010f3b5d783d then removed it the next commit. Would you mind sharing as to why?

    This somewhat opinionated PR is dependent on react-native-haptic-feedback and in order to experience the haptics you have to installed it. But it isn't necessary to have it installed for the react-native-hold-menu library to work. But it does give a quick and easy out of the box experience for users of this library. Let me know what you think and if this is a path you'd like to go down.

    opened by ksitko 12
  • Crash with latest version of reanimated2

    Crash with latest version of reanimated2

    Describe the bug Example app crashes with reanimated 2.0.1

    To Reproduce Upgrade to reanimated 2.0.1 Open example app

    Screenshots image

    Package versions See example app

    bug 
    opened by zhigang1992 10
  • Support expo-modules

    Support expo-modules

    As pointed on #53 since expo sdk 43 the react-native-unimodules is deprecated in favor of expo-modules, but this package installs the version 9.x of expo-blur & expo-haptics that uses unimodules.

    This can be fixed by moving the dependecies to peers so it will rely on the ones that the main project has installed, avoiding any conflict and making it compatible with any expo sdk version.

    Solves #53

    opened by sonnysantino 9
  • Hold Menu is transparent on iOS

    Hold Menu is transparent on iOS

    Describe the bug Background of menu is transparent on iOS.

    Expected behavior Expected background to be opaque (not able to see content behind menu)

    Actual behavior Menu is transparent, background is visible.

    Screenshots If applicable, add screenshots to help explain your problem. IMG_1915 IMG_1916

    Package versions

    • React: 17.0.2
    • React Native: 0.66.4
    • React Native Reanimated: 2.3.1
    • React Native Hold Menu: sonnysantino/react-native-hold-menu#fix/expo-modules
    • Expo: >=44.0.0-0 <45.0.0

    Additional context

    same code works fine on android.

    bug wip 
    opened by skam22 8
  • Error: Unable to resolve module @unimodules/core

    Error: Unable to resolve module @unimodules/core

    Describe the bug

    > 1 | import { NativeModulesProxy, requireNativeViewManager } from '@unimodules/core';
        |                                                               ^
      2 | import * as React from 'react';
      3 | import { findNodeHandle, View, StyleSheet } from 'react-native';
      4 | export default class BlurView extends React.Component {]
    

    Steps to reproduce the behavior:

    1. yarn add react-native-hold-menu
    2. import { HoldItem } from 'react-native-hold-menu';
    3. used ```<HoldItem items={MenuItems}>...
    4. yarn start
    5. See error

    Screenshots Screen Shot 2021-03-09 at 17 24 03

    Package versions

    • React: 17.0.1
    • React Native: 0.64.0-rc.4
    • React Native Reanimated: 2.0.0
    bug 
    opened by productdevbook 8
  • feat: add safeAreaInsets prop

    feat: add safeAreaInsets prop

    safeAreaInsets prop

    To be able to provide a better experience on opening menus, safe areas should be considered for both top and bottom. To do this, instead of passing separated props, added safeAreaInsets prop.

    Prev:

    const { bottom } = useSafeAreaInsets();
    <HoldMenuProvider paddingBottom={bottom} />
    

    Now:

    const safeAreaInsets = useSafeAreaInsets();
    <HoldMenuProvider safeAreaInsets={safeAreaInsets} />
    
    opened by enesozturk 7
  • ios not working

    ios not working

    Describe the bug null is not an object (evaluating 'NativeUnimoduleProxy.viewManagersNames')

    Screen Shot 1442-09-07 at 2 06 04 PM

    Package versions

    • React: 16.13.1
    • React Native: 0.63.3
    • React Native Reanimated: 2.0.0
    • React Native Hold Menu: 0.0.8
    • Expo: I don’t use expo in my project
    bug 
    opened by Turkialmalki 7
  • Ability to use without blur view and with taps instead of long presses

    Ability to use without blur view and with taps instead of long presses

    Hi! Thanks so much for the awesome library!

    I was wondering if you'd be open to supporting use of this package as more of a general purpose context menu? I'd like to use it to open a context menu on tap (instead of on long press), and without a blurred background. I'm thinking something like https://github.com/instea/react-native-popup-menu, but with the awesome animation and smoothness of this package.

    I forked and quickly updated it to work that way, and would be happy to open a PR eventually, but wasn't sure if that fit your vision for the package.

    feature 
    opened by jackspiva 6
  • type error HoldItem onpress prop

    type error HoldItem onpress prop

    There is a type error If I use the actionParams with multiple args.

    Type '(status: string, id: string) => void' is not assignable to type '(arg?: string | number | undefined) => void'.
    

    The original type of onPress?: (arg?: string | number) => void; Maybe this can be a solution for it: onPress?: (...args: (string | number)[]) => void;

    bug 
    opened by dancixx 5
  • react-native-unimodules is deprecated

    react-native-unimodules is deprecated

    The usage of react-native-unimodules is deprecated since Expo SDK 43. https://docs.expo.dev/bare/installing-unimodules/

    Please consider to migrate to Expo Modules https://docs.expo.dev/bare/installing-expo-modules/

    bug 
    opened by hirbod 5
  • Doesn't expire cached items prop with arrow functions

    Doesn't expire cached items prop with arrow functions

    Describe the bug Doesn't expire cached items prop with functions

    To Reproduce

    Pass function to onPress in items Even though you can pass updated items - it's cache on the lib side

    const holdItemMenuItems = (
      [
        {
          icon: 'copy-outline',
          text: 'Π‘ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ',
          onPress: () => {
            console.log('holdItemMenuItems text', text)
            Clipboard.setString(text)
          },
        },
      ]
    )
    

    Expected behavior It should call items with new function passed

    Actual behavior Caches function forever

    Screenshots

    https://user-images.githubusercontent.com/11584712/202919893-6302c8c8-cbef-4736-bd9b-202d597e5f60.mp4

    Package versions

    • React: 18.1.0
    • React Native: 0.70.5
    • React Native Reanimated: 2.13.0
    • React Native Hold Menu: latest
    • Expo: 47.0.6
    bug 
    opened by kesha-antonov 5
  • `HoldItem` react context is incorrect

    `HoldItem` react context is incorrect

    Describe the bug HoldItem do not respect the react context in which they are rendered in. They seem to be rendered in the context of their HoldMenuProvider

    To Reproduce

    import React from 'react';
    import { HoldItem, HoldMenuProvider } from "react-native-hold-menu";
    
    const MyContext = React.createContext(0);
    
    const holdItemMenu = [{ text:"test", onPress:()=>{} }]
    
    const MyComponent = ()=>{
      const context = React.useContext(MyContext);
      
      return (
        <HoldItem>
          <View>{context}</View>
        </HoldItem>
      )
    }
    
    export const App = ()=>{
      return (
        <HoldMenuProvider>
          <MyContext.Provider value={123}>
            <MyComponent />
          </MyContext.Provider>
        <HoldMenuProvider>
      )
    }
    

    n.b. this is a simplified, untested example of what I'm experiencing. LMK if there are any issues.

    Expected behavior In the example above, I expect MyComponent to render 123.

    I expect this because it is rendered inside of that context

    Actual behavior In the example above,MyComponent renders 0.

    It appears MyComponent is actually rendered where HoldMenuProvider is rendered, receiving that context

    Screenshots None

    Package versions

    • React: 18.2.0
    • React Native: 0.69.6
    • React Native Reanimated: 2.9.1
    • React Native Hold Menu: 0.1.5
    • Expo: 46.0.9

    Additional context Add any other context about the problem here.

    bug 
    opened by mrjackdavis 2
  • Expo Managed app support

    Expo Managed app support

    Describe the bug Upon following the instructions in this package's README and also the dependencies instructions, I've come up to this error:

    TypeError: (0, _expoModulesCore.requireNativeModule) is not a function. (In '(0, _expoModulesCore.requireNativeModule)('ExpoHaptics')', '(0, _expoModulesCore.requireNativeModule)' is undefined)
    at node_modules/react-native/Libraries/Core/ExceptionsManager.js:104:6 in reportException
    at node_modules/react-native/Libraries/Core/ExceptionsManager.js:172:19 in handleException
    at node_modules/react-native/Libraries/Core/setUpErrorHandling.js:24:6 in handleError
    at node_modules/@react-native/polyfills/error-guard.js:49:36 in ErrorUtils.reportFatalError
    at node_modules/metro-runtime/src/polyfills/require.js:204:6 in guardedLoadModule
    at http://192.168.1.100:19000/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&strict=false&minify=false:284752:3 in global code
    

    To Reproduce Steps to reproduce the behavior:

    1. yarn add react-native-hold-menu
    2. npx expo install react-native-reanimated
    3. expo install react-native-gesture-handler
    4. npx expo install expo-blur
    5. npx expo install expo-haptics

    Expected behavior Hold menu working

    Actual behavior App doesn't run with the following error being displayed: TypeError: (0, _expoModulesCore.requireNativeModule) is not a function. (In '(0, _expoModulesCore.requireNativeModule).

    Screenshots image

    Package versions

    • React: 17.0.1
    • React Native: 0.64.3
    • React Native Reanimated: ~2.3.1
    • React Native Hold Menu: 0.1.5
    • Expo: ~44.0.0
    • Expo Haptics: ~11.1.0
    • Expo Blur: ~11.0.0

    Additional context From my understanding, this could be an issue with expo-modules-core not supporting expo managed apps yet - hence the API documentation for setup not being valid.

    However, if that is true this package could have a more clear description of what's going on with the expo compability. It says it's compatible but it's not clear if it supports bare, managed or both types of apps.

    bug 
    opened by fabiofcferreira 1
  • Menu displays behind modal screen

    Menu displays behind modal screen

    Describe the bug When HoldMenuItem is used in a screen that has presentation: 'modal'. The hold-items display behind the modal instead of on top.

    Expected behavior The blur and menu items should be displayed on top of the modal view.

    Actual behavior The blur and menu items are displayed behind the modal view.

    Screenshots

    Package versions

    • React: 18.0.0
    • React Native: 0.69.5
    • React Native Reanimated: 2.9.1
    • React Native Hold Menu: 0.1.5
    • Expo: 46.0.0
    bug 
    opened by Joehoel 1
  • Bottom item is too short

    Bottom item is too short

    Describe the bug On the latest version (including in the example project), the final item of the context menu has less height than the rest.

    Screenshot 2022-08-10 at 10 18 45 PM

    To Reproduce Steps to reproduce the behavior:

    1. Run example
    2. Open any context menu
    3. See error

    Package versions

    • React: 18.0.0
    • React Native: 0.69.4
    • React Native Reanimated: 2.9.1
    • React Native Hold Menu: 0.1.5
    • Expo: 46.0.0-beta.6
    bug 
    opened by r0hin 0
Releases(v0.1.5)
Owner
Enes
Software Engineer. Enthusiast of React & React Native, Loves paragliding πŸͺ‚
Enes
Left navigation menu. Get data from JSON file and display simple form menu.

Left Navbar Menu Left navigation menu. Get data from JSON file and display simple form menu. User Interface created using React and Typescript. App st

Wojtek 5 May 24, 2021
Simple Context menu component for react showing all parent's node menus in theirs contexts.

Simple Context menu component for react showing all inherited parents menu with SSR compatibility.

Nathan Braun 6 Nov 13, 2022
Add a context menu to your react app with ease

Documentation Go here. Installation Using yarn $ yarn add react-contexify Using npm $ npm install --save react-contexify The gist import React from 'r

Fadi Khadra 851 Dec 2, 2022
Animated hamburger menu icons for React (1.5 KB) πŸ”

β€Œ β€Œ Animated hamburger menu icons for React Hamburger menu icons for React, with CSS-driven transitions. Created to be as elegant and performant as po

Luuk de Vlieger 690 Nov 28, 2022
React Dropdown Menu

React Dropdown Menu

Mikkel Laursen 142 Dec 3, 2022
Hamburger Menu React JS Using Third Party Package ReactJS - Popup

In this project, let's build a Hamburger Menu app by applying the concepts we have learned till now. Refer to the image below: Design Files Click to v

null 2 Dec 6, 2021
A simple, data-driven, light-weight React Tree Menu component

React Simple Tree Menu Inspired by Downshift, a simple, data-driven, light-weight React Tree Menu component that: does not depend on any UI framework

Huang-Ming Chang 120 Dec 1, 2022
A simple sliding side menu component for React

Cheeseburger Menu A simple sliding side menu component for React. This component provides the sliding menu only, not the hamburger button. For your bu

Eddie McLean 19 May 27, 2022
React dropdown menu components

react-menu-list This project is a set of components for building menus. This project works well for dropdown and autocomplete menus. The menus are cor

Streak 79 Nov 16, 2022
A react component that displays an unlimited deep menu

react-infinity-menu An unlimited deep side menu Live Demo Demo Installation npm install react-infinity-menu How to use import InfinityMenu from "react

Social Tables 57 May 9, 2022
Radial Menu for FiveM,built with React

BCS Radial Menu This project is to freshen up the options for free radial menu f

BagusCodeStudio 13 Nov 7, 2022
πŸͺ A stylized command menu for React.

?? Superkey is under development and is not ready for production. If you have any bugs or problems please create an issue. ?? Website (working ?? ) β€’

Pablo Hdez 11 Nov 7, 2022
Smart data-driven menu rendered in an overlay

React Data Menu Smart data-driven menu rendered in an overlay. Hints-based aligning with custom renderers and factories. Never clipped by other compon

Danko Kozar 106 Sep 11, 2022
React dismissable context and hook with layers (nesting) support

Context and hook to add support for nested, auto-dismissable layers. State can be globally controlled through context. Best used with react-popper.

Voiceflow 13 Nov 15, 2022
A react lib for building circular menus in a very easy and handy way.

react-planet A react lib for building circular menus in a very easy and handy way. Live-Demo: STORYBOOK Read the full story @ Medium or innFactory-Blo

innFactory 140 Nov 16, 2022
:art: Off-canvas menus for React.

React Off-Canvas Off-canvas menus for React. Installation $ npm install --save react-offcanvas Usage Basic Usage <OffCanvas width={300} transition

Vu Tran 38 Nov 10, 2022
A simple Hook for creating fully accessible dropdown menus in React

This Hook handles all the accessibility logic when building a dropdown menu, dropdown button, etc., and leaves the design completely up to you. It also handles the logic for closing the menu when you click outside of it.

Sparksuite 109 Sep 27, 2022
Tiny react library for building tooltips, flyovers, menus and more

Postel ?? Postel is a single component that you can easily extend into customized tooltips, dropdowns, flyovers – any type of UI which would make sens

Tim 76 Aug 9, 2022
Navigation drawer built with the awesome react-motion

ARCHIVED because I didn't have time nor use for this for a long time. I'd be happy to transfer ownership if someone is interested. react-motion-drawer

Christoph Hermann 219 Aug 9, 2022