A flexible dropdown menu component for Android and iOS that is similar to Android's Spinner.
A menu component for Android and iOS that provides a dropdown similar to Android's Spinner, but does not retain a persistent selection.
The API is very flexible so you are free to extend the styling and behaviour.
$ npm install react-native-menu --save
Or with yarn:
$ yarn add react-native-menu
iOS | Android |
---|---|
import React, { View, Text, AppRegistry } from 'react-native';
import Menu, { MenuContext, MenuOptions, MenuOption, MenuTrigger } from 'react-native-menu';
const App = () => (
// You need to place a MenuContext somewhere in your application, usually at the root.
// Menus will open within the context, and only one menu can open at a time per context.
<MenuContext style={{ flex: 1 }}>
<TopNavigation/>
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}><Text>Hello!</Text></View>
</MenuContext>
);
const TopNavigation = () => (
<View style={{ padding: 10, flexDirection: 'row', backgroundColor: 'pink' }}>
<View style={{ flex: 1 }}><Text>My App</Text></View>
<Menu onSelect={(value) => alert(`User selected the number ${value}`)}>
<MenuTrigger>
<Text style={{ fontSize: 20 }}>⋮</Text>
</MenuTrigger>
<MenuOptions>
<MenuOption value={1}>
<Text>One</Text>
</MenuOption>
<MenuOption value={2}>
<Text>Two</Text>
</MenuOption>
</MenuOptions>
</Menu>
</View>
);
AppRegistry.registerComponent('Example', () => App);
Important: In order for the <Menu/>
to work, you need to mount <MenuContext/>
as an ancestor to <Menu/>
. This allows
the menu to open on top of all other components mounted under <MenuContext/>
-- basically, the menu will be moved
to be the last child of the context.
You must also have a <MenuTrigger/>
and a <MenuOptions/>
as direct children under <Menu/>
. The MenuTrigger
component
opens the menu when pressed. The MenuOptions
component can take any children, but you need at least one MenuOption
child in order for the menu to actually do anything.
The MenuOption
component can take any children.
Please refer to the full working example here.
MenuTrigger
and MenuOption
componentsBy default, the MenuTrigger
and MenuOption
components render with a
TouchableWithoutFeedback
component, however this may make the menu feel
unnatural in your app.
To override this, both components will take a renderTouchable
property, which
should be a function which returns an alternate component to use. For example:
import { TouchableOpacity, Text } from 'react-native';
import Menu, { MenuOptions, MenuOption, MenuTrigger } from 'react-native-menu';
const renderTouchable = () => <TouchableOpacity/>;
const menu = () => (
<Menu>
<MenuTrigger renderTouchable={renderTouchable}>
<Text>Trigger</Text>
</MenuTrigger>
<MenuOptions>
<MenuOption value={1} renderTouchable={renderTouchable}>
<Text>One</Text>
</MenuOption>
<MenuOption value={2} renderTouchable={renderTouchable}>
<Text>Two</Text>
</MenuOption>
</MenuOptions>
</Menu>
);
Methods:
true
if menu is openProps:
style
-- Overrides default style properties (user-defined style will take priority)onCloseMenu
-- Handler that will be called with the state of MenuContext
, if defined.Methods:
Props:
onSelect
-- This function is called with the value the MenuOption
that has been selected by the userProps:
disabled
-- If true, then this trigger is not pressablestyle
-- Overrides default style properties (user-defined style will take priority)renderTouchable
-- A function which can override the defaultTouchableWithoutFeedback
component by returning a different component. SeeProps:
optionsContainerStyle
-- Provides custom styling for options containerrenderOptionsContainer
-- A function that renders takes in the MenuOptions
element and renders a container elementScrollView
.For example, if you want to change the options width to 300
, you can use <MenuOptions optionsContainerStyle={{ width: 300 }}>
.
To further customize the rendered content you can do something like
<MenuOptions renderOptionsContainer={(options) => <SomeCustomContainer>{options}</SomeCustomContainer>}>
.
Props:
disabled
-- If true, then this option is not selectablestyle
-- Overrides default style properties (user-defined style will take priority)renderTouchable
-- A function which can override the defaultTouchableWithoutFeedback
component by returning a different component. SeeMenu
components under one `MenuContextMenu
).Install dev modules:
yarn
yarn test:unit
Make sure you have a connected android device. You find list devices using adb devices
.
yarn test:integration
Contributions are welcome! Just open an issues with any ideas or pull-requests. I will take a look when I have time. :)