
Security News
CVE Volume Surges Past 48,000 in 2025 as WordPress Plugin Ecosystem Drives Growth
CVE disclosures hit a record 48,185 in 2025, driven largely by vulnerabilities in third-party WordPress plugins.
@exodus/react-native-menu
Advanced tools
iOS14+ UIMenu components for react-native. Falls back to ActionSheet for versions below iOS14.
| iOS 14+ | iOS 13 |
|---|---|
![]() | ![]() |
via npm:
npm install @exodus/react-native-menu
via yarn:
yarn add @exodus/react-native-menu
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.
The package is automatically linked when building the app. All you need to do is:
npx pod-install
import { MenuView, MenuComponentRef } from "@exodus/react-native-menu";
const App = () => {
const menuRef = useRef < MenuComponentRef > null;
return (
<View style={styles.container}>
<MenuView
ref={menuRef}
title="Menu Title"
onPressAction={({ nativeEvent }) => {
console.warn(JSON.stringify(nativeEvent));
}}
actions={[
{
id: "add",
title: "Add",
titleColor: "#2367A2",
image: "plus",
imageColor: "#2367A2",
subactions: [
{
id: "nested1",
title: "Nested action",
titleColor: "rgba(250,180,100,0.5)",
subtitle: "State is mixed",
image: "heart.fill",
imageColor: "rgba(100,200,250,0.3)",
state: "mixed",
},
{
id: "nestedDestructive",
title: "Destructive Action",
attributes: {
destructive: true,
},
image: "trash",
},
],
},
{
id: "share",
title: "Share Action",
titleColor: "#46F289",
subtitle: "Share action on SNS",
image: "square.and.arrow.up",
imageColor: "#46F289",
state: "on",
},
{
id: "destructive",
title: "Destructive Action",
attributes: {
destructive: true,
},
image: "trash",
},
]}
shouldOpenOnLongPress={false}
>
<View style={styles.button}>
<Text style={styles.buttonText}>Test</Text>
</View>
</MenuView>
</View>
);
};
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.
title (iOS only)The title of the menu.
| Type | Required |
|---|---|
| string | Yes |
shouldOpenOnLongPressBoolean determining if menu should open after long press or on normal press
| Type | Required |
|---|---|
| boolean | No |
actionsActions to be displayed in the menu.
| Type | Required |
|---|---|
| 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.
| Type | Required |
|---|---|
| enum('light', 'dark') | No |
MenuActionObject 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;
/**
* (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;
/**
* (iOS13+ only)
* - The action's image.
* - Allows icon name included in SF Symbol
* @example
* image="plus"
*/
image?: string;
/**
* (iOS13+ only)
* - The action's image color.
*/
imageColor?: number | ColorValue;
/**
* (iOS14+ only)
* - Actions to be displayed in the sub menu
*/
subactions?: MenuAction[];
};
MenuAttributesThe 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;
};
MenuStateThe 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";
onPressActionCallback function that will be called when selecting a menu item. It will contain id of the given action.
| Type | Required |
|---|---|
| ({nativeEvent}) => void | No |
onCloseMenuCallback function that will be called when the menu is dismissed. This event fires at the start of the dismissal, before any animations complete.
| Type | Required |
|---|---|
| () => void | No |
onOpenMenuCallback function that will be called when the menu is opened. This event fires right before the menu is displayed.
| Type | Required |
|---|---|
| () => void | No |
Example usage:
<MenuView
onOpenMenu={() => {
console.log("Menu was opened");
}}
onCloseMenu={() => {
console.log("Menu was closed");
}}
>
<View>
<Text>Open Menu</Text>
</View>
</MenuView>
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 "@exodus/react-native-menu";
jest.mock("@exodus/react-native-menu", () => ({
MenuView: jest.fn((props: MenuComponentProps) => {
const React = require("react");
class MockMenuView extends React.Component {
render() {
return React.createElement(
"View",
{ testID: props.testID },
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);
}),
}));
See the contributing guide to learn how to contribute to the repository and the development workflow.
MIT
FAQs
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
CVE disclosures hit a record 48,185 in 2025, driven largely by vulnerabilities in third-party WordPress plugins.

Security News
Socket CEO Feross Aboukhadijeh joins Insecure Agents to discuss CVE remediation and why supply chain attacks require a different security approach.

Security News
Tailwind Labs laid off 75% of its engineering team after revenue dropped 80%, as LLMs redirect traffic away from documentation where developers discover paid products.