Convert Figma logo to code with AI

react-native-menu logomenu

UIMenu Component for React Native

1,064
65
1,064
43

Top Related Projects

Material Design for React Native (Android & iOS)

Cross-Platform React Native UI Toolkit

UI Components Library for React Native

Mobile-first, accessible components for React Native & Web to build consistent UI across Android, iOS and Web.

:boom: React Native UI Library based on Eva Design System :new_moon_with_face::sparkles:Dark Mode

An enhanced, animated, customizable Modal for React Native.

Quick Overview

React Native Menu is a flexible and customizable menu component for React Native applications. It provides a simple way to create dropdown menus, context menus, and other menu-based UI elements with native performance and a consistent look across platforms.

Pros

  • Easy to integrate and use in React Native projects
  • Highly customizable with support for custom styling and animations
  • Cross-platform compatibility (iOS and Android)
  • Good performance due to native implementation

Cons

  • Limited documentation and examples
  • Some reported issues with complex nested menus
  • Occasional compatibility issues with certain React Native versions
  • Relatively small community compared to some other UI libraries

Code Examples

  1. Basic Menu Usage:
import Menu, { MenuItem } from 'react-native-menu';

const MyComponent = () => (
  <Menu>
    <MenuItem onPress={() => console.log('Item 1 pressed')}>Item 1</MenuItem>
    <MenuItem onPress={() => console.log('Item 2 pressed')}>Item 2</MenuItem>
    <MenuItem onPress={() => console.log('Item 3 pressed')}>Item 3</MenuItem>
  </Menu>
);
  1. Custom Trigger Component:
import Menu, { MenuTrigger, MenuOptions, MenuOption } from 'react-native-menu';

const CustomTrigger = () => (
  <View style={styles.triggerView}>
    <Text>Open Menu</Text>
  </View>
);

const MyComponent = () => (
  <Menu>
    <MenuTrigger customStyles={triggerStyles} CustomTrigger={CustomTrigger} />
    <MenuOptions>
      <MenuOption onSelect={() => alert('Option 1')}>
        <Text>Option 1</Text>
      </MenuOption>
      <MenuOption onSelect={() => alert('Option 2')}>
        <Text>Option 2</Text>
      </MenuOption>
    </MenuOptions>
  </Menu>
);
  1. Nested Menu:
import Menu, { MenuOptions, MenuOption, MenuTrigger } from 'react-native-menu';

const NestedMenu = () => (
  <Menu>
    <MenuTrigger text='Main Menu' />
    <MenuOptions>
      <MenuOption value={1} text='Option 1' />
      <Menu>
        <MenuTrigger text='Submenu' />
        <MenuOptions>
          <MenuOption value={2} text='Submenu Option 1' />
          <MenuOption value={3} text='Submenu Option 2' />
        </MenuOptions>
      </Menu>
    </MenuOptions>
  </Menu>
);

Getting Started

  1. Install the package:

    npm install react-native-menu
    
  2. Import the components in your React Native file:

    import Menu, { MenuItem, MenuDivider } from 'react-native-menu';
    
  3. Use the Menu component in your JSX:

    <Menu>
      <MenuItem onPress={() => {}}>Menu Item 1</MenuItem>
      <MenuItem onPress={() => {}}>Menu Item 2</MenuItem>
      <MenuDivider />
      <MenuItem onPress={() => {}}>Menu Item 3</MenuItem>
    </Menu>
    
  4. Customize the menu appearance and behavior using props and custom styles as needed.

Competitor Comparisons

Material Design for React Native (Android & iOS)

Pros of react-native-paper

  • Comprehensive UI component library with a wide range of pre-built components
  • Follows Material Design guidelines, ensuring a consistent and modern look
  • Active development and regular updates, with good community support

Cons of react-native-paper

  • Larger bundle size due to the extensive component library
  • May require additional configuration for custom theming and styling
  • Some components might be overly complex for simple use cases

Code Comparison

react-native-paper:

import { Menu } from 'react-native-paper';

<Menu
  visible={visible}
  onDismiss={closeMenu}
  anchor={<Button onPress={openMenu}>Show menu</Button>}
>
  <Menu.Item onPress={() => {}} title="Item 1" />
  <Menu.Item onPress={() => {}} title="Item 2" />
</Menu>

react-native-menu:

import Menu, { MenuItem } from 'react-native-menu';

<Menu onSelect={value => alert(`Selected ${value}`)}>
  <MenuItem value="item1">Item 1</MenuItem>
  <MenuItem value="item2">Item 2</MenuItem>
</Menu>

Summary

react-native-paper offers a more comprehensive set of components and follows Material Design guidelines, making it suitable for larger projects requiring a consistent UI. However, it may be overkill for simpler applications. react-native-menu provides a more focused solution for menu components, with a simpler API and potentially smaller bundle size, but lacks the broader component ecosystem of react-native-paper.

Cross-Platform React Native UI Toolkit

Pros of react-native-elements

  • Comprehensive UI toolkit with a wide range of pre-built components
  • Active development and community support
  • Customizable themes and consistent styling across components

Cons of react-native-elements

  • Larger package size due to the extensive component library
  • May require more setup and configuration for specific use cases
  • Potential performance impact when using many complex components

Code Comparison

react-native-elements:

import { Button, Icon } from 'react-native-elements';

<Button
  icon={<Icon name="arrow-right" size={15} color="white" />}
  title="Button with Icon"
/>

react-native-menu:

import Menu, { MenuItem } from 'react-native-menu';

<Menu>
  <MenuItem onPress={() => {}}>Menu Item 1</MenuItem>
  <MenuItem onPress={() => {}}>Menu Item 2</MenuItem>
</Menu>

Summary

react-native-elements offers a comprehensive UI toolkit with a wide range of components, making it suitable for larger projects requiring consistent styling. However, it may have a larger package size and potential performance impact.

react-native-menu focuses specifically on menu components, providing a lightweight solution for implementing menus in React Native applications. It's more suitable for projects that only need menu functionality without the overhead of a full UI toolkit.

Choose react-native-elements for comprehensive UI needs and consistent styling across your app. Opt for react-native-menu if you only require menu functionality and prefer a lightweight solution.

UI Components Library for React Native

Pros of react-native-ui-lib

  • Comprehensive UI component library with a wide range of pre-built components
  • Customizable theming system for consistent design across the app
  • Active development and regular updates

Cons of react-native-ui-lib

  • Larger package size due to the extensive component library
  • Steeper learning curve for developers new to the library

Code Comparison

react-native-menu/menu:

import Menu, { MenuItem } from 'react-native-menu';

<Menu>
  <MenuItem onPress={() => {}}>Item 1</MenuItem>
  <MenuItem onPress={() => {}}>Item 2</MenuItem>
</Menu>

react-native-ui-lib:

import { View, Button, Dialog } from 'react-native-ui-lib';

<View>
  <Button label="Open Dialog" onPress={() => this.dialog.show()} />
  <Dialog visible={this.state.showDialog} onDismiss={() => this.setState({showDialog: false})}>
    <Dialog.Content>
      <Text>Dialog content</Text>
    </Dialog.Content>
  </Dialog>
</View>

Summary

react-native-ui-lib offers a more comprehensive set of UI components and theming options compared to react-native-menu/menu, which focuses specifically on menu functionality. While react-native-ui-lib provides greater flexibility and customization, it comes with a larger package size and potentially steeper learning curve. The choice between the two depends on the specific needs of the project and the desired level of control over UI components.

Mobile-first, accessible components for React Native & Web to build consistent UI across Android, iOS and Web.

Pros of NativeBase

  • Comprehensive UI component library with a wide range of pre-built components
  • Customizable theme system for consistent styling across the app
  • Active development and community support

Cons of NativeBase

  • Larger bundle size due to the extensive component library
  • Steeper learning curve for developers new to the framework
  • May require additional configuration for optimal performance

Code Comparison

NativeBase example:

import { Box, Text, Button } from 'native-base';

const MyComponent = () => (
  <Box>
    <Text>Hello, NativeBase!</Text>
    <Button>Click me</Button>
  </Box>
);

Menu example:

import { Menu, MenuOptions, MenuOption, MenuTrigger } from 'react-native-menu';

const MyMenu = () => (
  <Menu>
    <MenuTrigger text='Select option' />
    <MenuOptions>
      <MenuOption value={1} text='Option 1' />
      <MenuOption value={2} text='Option 2' />
    </MenuOptions>
  </Menu>
);

While NativeBase provides a more comprehensive set of UI components and theming capabilities, Menu focuses specifically on creating customizable dropdown menus. NativeBase may be better suited for larger projects requiring a consistent design system, while Menu offers a lightweight solution for implementing menu functionality in React Native applications.

:boom: React Native UI Library based on Eva Design System :new_moon_with_face::sparkles:Dark Mode

Pros of react-native-ui-kitten

  • Comprehensive UI library with a wide range of pre-built components
  • Customizable theming system for easy styling
  • Active development and community support

Cons of react-native-ui-kitten

  • Larger bundle size due to extensive component library
  • Steeper learning curve for customization
  • May require more setup and configuration

Code Comparison

react-native-ui-kitten:

import { Button, Text } from '@ui-kitten/components';

const MyButton = () => (
  <Button onPress={() => console.log('Pressed')}>
    <Text>Click me</Text>
  </Button>
);

react-native-menu:

import Menu from 'react-native-menu';

const MyMenu = () => (
  <Menu>
    <Menu.Item onPress={() => console.log('Option 1')}>Option 1</Menu.Item>
    <Menu.Item onPress={() => console.log('Option 2')}>Option 2</Menu.Item>
  </Menu>
);

Summary

react-native-ui-kitten offers a more comprehensive UI solution with extensive theming capabilities, while react-native-menu focuses specifically on menu components. UI Kitten provides a wider range of components but may have a larger footprint and learning curve. react-native-menu is more lightweight and specialized for menu functionality. The choice between the two depends on project requirements and the desired level of UI customization.

An enhanced, animated, customizable Modal for React Native.

Pros of react-native-modal

  • More comprehensive and feature-rich modal solution
  • Highly customizable with various animation options
  • Actively maintained with frequent updates and bug fixes

Cons of react-native-modal

  • Larger package size due to additional features
  • Steeper learning curve for advanced customizations
  • May introduce performance overhead for simple use cases

Code Comparison

react-native-modal:

import Modal from 'react-native-modal';

<Modal isVisible={isModalVisible} onBackdropPress={toggleModal}>
  <View style={styles.modalContent}>
    <Text>Modal Content</Text>
    <Button title="Close" onPress={toggleModal} />
  </View>
</Modal>

react-native-menu:

import Menu from 'react-native-menu';

<Menu>
  <Menu.Item onPress={handlePress}>Menu Item 1</Menu.Item>
  <Menu.Item onPress={handlePress}>Menu Item 2</Menu.Item>
</Menu>

While react-native-modal provides a full-featured modal solution with extensive customization options, react-native-menu focuses specifically on creating menu components. The choice between the two depends on the specific requirements of your project. If you need a versatile modal system with animations and customization options, react-native-modal is the better choice. However, if you're looking for a simpler, menu-specific solution, react-native-menu might be more suitable.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

@react-native-menu/menu

Supports Android, iOSGithub Action Badge npm

Android PopupMenu and iOS14+ UIMenu components for react-native. Falls back to ActionSheet for versions below iOS14.

AndroidiOS 14+iOS 13

Installation

via npm:

npm install @react-native-menu/menu

via yarn:

yarn add @react-native-menu/menu

Installing on iOS with React Native 0.63 and above

There is an issue(https://github.com/facebook/react-native/issues/29246) causing projects with this module to fail on build on React Native 0.63 and above. This issue may be fixed in future versions of react native. As a work around, look for lines in [YourPrject].xcodeproj under LIBRARY_SEARCH_PATHS with "\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"", and change swift-5.0 to swift-5.3.

Linking

The package is automatically linked when building the app. All you need to do is:

npx pod-install

Usage

import { MenuView, MenuComponentRef } from '@react-native-menu/menu';

// ...

const App = () => {
  const menuRef = useRef<MenuComponentRef>(null);
  return (
    <View style={styles.container}>
      <Button
        title="Show Menu with ref (Android only)"
        onPress={() => menuRef.current?.show()}
      />
      <MenuView
        ref={menuRef}
        title="Menu Title"
        onPressAction={({ nativeEvent }) => {
          console.warn(JSON.stringify(nativeEvent));
        }}
        actions={[
          {
            id: 'add',
            title: 'Add',
            titleColor: '#2367A2',
            image: Platform.select({
              ios: 'plus',
              android: 'ic_menu_add',
            }),
            imageColor: '#2367A2',
            subactions: [
              {
                id: 'nested1',
                title: 'Nested action',
                titleColor: 'rgba(250,180,100,0.5)',
                subtitle: 'State is mixed',
                image: Platform.select({
                  ios: 'heart.fill',
                  android: 'ic_menu_today',
                }),
                imageColor: 'rgba(100,200,250,0.3)',
                state: 'mixed',
              },
              {
                id: 'nestedDestructive',
                title: 'Destructive Action',
                attributes: {
                  destructive: true,
                },
                image: Platform.select({
                  ios: 'trash',
                  android: 'ic_menu_delete',
                }),
              },
            ],
          },
          {
            id: 'share',
            title: 'Share Action',
            titleColor: '#46F289',
            subtitle: 'Share action on SNS',
            image: Platform.select({
              ios: 'square.and.arrow.up',
              android: 'ic_menu_share',
            }),
            imageColor: '#46F289',
            state: 'on',
          },
          {
            id: 'destructive',
            title: 'Destructive Action',
            attributes: {
              destructive: true,
            },
            image: Platform.select({
              ios: 'trash',
              android: 'ic_menu_delete',
            }),
          },
        ]}
        shouldOpenOnLongPress={false}
      >
        <View style={styles.button}>
          <Text style={styles.buttonText}>Test</Text>
        </View>
      </MenuView>
    </View>
  );
};

Declarative usage

It's also possible to obtain the action is a more React-ish, declarative fashion. Refer to the react-to-imperative package, and see an example here.

Reference

Props

ref (Android only)

Ref to the menu component.

TypeRequired
refNo

title (iOS only)

The title of the menu.

TypeRequired
stringYes

isAnchoredToRight (Android only)

Boolean determining if menu should anchored to right or left corner of parent view.

TypeRequired
booleanNo

shouldOpenOnLongPress

Boolean determining if menu should open after long press or on normal press

TypeRequired
booleanNo

actions

Actions to be displayed in the menu.

TypeRequired
MenuAction[]Yes

themeVariant (iOS only)

String to override theme of the menu. If you want to control theme universally across your app, see this package.

TypeRequired
enum('light', 'dark')No

MenuAction

Object representing Menu Action.

export type MenuAction = {
  /**
   * Identifier of the menu action.
   * The value set in this id will be returned when menu is selected.
   */
  id?: string;
  /**
   * The action's title.
   */
  title: string;
  /**
   * (Android only)
   * The action's title color.
   * @platform Android
   */
  titleColor?: number | ColorValue;
  /**
   * (iOS14+ only)
   * An elaborated title that explains the purpose of the action.
   * @platform iOS
   */
  subtitle?: string;
  /**
   * The attributes indicating the style of the action.
   */
  attributes?: MenuAttributes;
  /**
   * (iOS14+ only)
   * The state of the action.
   * @platform iOS
   */
  state?: MenuState;
  /**
   * (Android and iOS13+ only)
   * - The action's image.
   * - Allows icon name included in project or system (Android) resources drawables and
   * in SF Symbol (iOS)
   * @example // (iOS)
   * image="plus"
   * @example // (Android)
   * image="ic_menu_add"
   */
  image?: string;
  /**
   * (Android and iOS13+ only)
   * - The action's image color.
   */
  imageColor?: number | ColorValue;
  /**
   * (Android and iOS14+ only)
   * - Actions to be displayed in the sub menu
   * - On Android it does not support nesting next sub menus in sub menu item
   */
  subactions?: MenuAction[];
};

MenuAttributes

The attributes indicating the style of the action.

type MenuAttributes = {
  /**
   * An attribute indicating the destructive style.
   */
  destructive?: boolean;
  /**
   * An attribute indicating the disabled style.
   */
  disabled?: boolean;
  /**
   * An attribute indicating the hidden style.
   */
  hidden?: boolean;
};

MenuState

The state of the action.

/**
 * The state of the action.
 * - off: A constant indicating the menu element is in the “off” state.
 * - on: A constant indicating the menu element is in the “on” state.
 * - mixed: A constant indicating the menu element is in the “mixed” state.
 */
type MenuState = 'off' | 'on' | 'mixed';

onPressAction

Callback function that will be called when selecting a menu item. It will contain id of the given action.

TypeRequired
({nativeEvent}) => voidNo

Events

onCloseMenu

Callback function that will be called when the menu is dismissed. This event fires at the start of the dismissal, before any animations complete.

TypeRequired
() => voidNo

onOpenMenu

Callback function that will be called when the menu is opened. This event fires right before the menu is displayed.

TypeRequired
() => voidNo

Example usage:

<MenuView
  onOpenMenu={() => {
    console.log('Menu was opened');
  }}
  onCloseMenu={() => {
    console.log('Menu was closed');
  }}
  // ... other props
>
  <View>
    <Text>Open Menu</Text>
  </View>
</MenuView>

Testing with Jest

In some cases, you might want to mock the package to test your components. You can do this by using the jest.mock function.

import type { MenuComponentProps } from '@react-native-menu/menu';

jest.mock('@react-native-menu/menu', () => ({
  MenuView: jest.fn((props: MenuComponentProps) => {
    const React = require('react');

    class MockMenuView extends React.Component {
      render() {
        return React.createElement(
          'View',
          { testID: props.testID },
          // Dynamically mock each action
          props.actions.map(action =>
            React.createElement('Button', {
              key: action.id,
              title: action.title,
              onPress: () => {
                if (action.id && props?.onPressAction) {
                  props.onPressAction({ nativeEvent: { event: action.id } });
                }
              },
              testID: action.id
            })
          ),
          this.props.children
        );
      }
    }

    return React.createElement(MockMenuView, props);
  })
}));

Contributing

See the contributing guide to learn how to contribute to the repository and the development workflow.

License

MIT

NPM DownloadsLast 30 Days