| .github/workflows | ||
| android | ||
| assets | ||
| docs | ||
| example | ||
| ios | ||
| scripts | ||
| src | ||
| .editorconfig | ||
| .gitattributes | ||
| .gitignore | ||
| .nvmrc | ||
| .yarnrc | ||
| babel.config.js | ||
| CONTRIBUTING.md | ||
| LICENSE | ||
| package.json | ||
| react-native-ios-context-menu.podspec | ||
| react-native.config.js | ||
| README-old.md | ||
| README.md | ||
| tsconfig.build.json | ||
| tsconfig.json | ||
| yarn.lock | ||
react-native-ios-context-menu
🚧⚠️ Library + Documentation Re-Write WIP ⚠️🚧
📝 Check TODO.md for progress on re-write.
- ❤️ Support the new API's introduced in iOS 15.
- 🧡 New
SFSymbols+ menu icon config API. - 💛 Support for use with Mac Catalyst (e.g. configuring the mac's menu bar + the iPad's shortcuts/menu bar).
- 💚 Typescript re-write (for better autocomplete).
- 💙 Documentation re-write (so its actually usable + better examples).
- 💜 ...and fixing all the bugs + issues so far 😅
- The documentation is incomplete (some parts/sections are marked as TBA i.e. "to be added").
- Some of the links in the documentation are broken (i.e. the URL points to
PLACE_HOLDER_LINK). - For now, please see the Usage And Examples section for information on how to use this library.
| Notice |
|---|
| 📝 Note #1: A future major version of this library will introduce breaking changes to the API (mainly just renaming some of the properties) in order to add new features (and better types). However, the next minor version of this library will not introduce any breaking changes but will instead focus on adding typescript annotations and fixing the existing bugs. |
| 📝 Note #2: The documentation + examples are currently being rewritten. 💅 README-old.md — The old version of the documentation (archived).💖 example/src/examples — The typescript rewrite of the examples (WIP). |
Versions
| Library Version | Compatibility |
|---|---|
1.6.2 |
iOS 10 to iOS 15 Xcode 12+ |
1.4 |
iOS 10 to iOS 15 Xcode 13+ |
1.3 and Below |
iOS 10 to 14 Xcode 12+ |
📝 Note: Supports projects targeting iOS 10 but will use the action sheet fallback when running on iOS 12 and older.
A. Introduction
A react native component to use UIMenu on iOS 13 and later.
A.1. Gifs and Demos
📝 Note: These gifs are from an older version of the library running on iOS 13 (see Usage And Examples section for updated example gifs).
ContextMenuView Examples, Left: Example 1, Example 2, and Right: Example 3, Example 4

ContextMenuView examples, Left: Example 5, Example 6, and Right: Example 7, Example 8

ContextMenuView example, Left: Example 9, and Right: Example 10

ContextMenuView examples, Left: Example 11, Example 12, and Right: Example 13, Example 14

ContextMenuView examples, Left: Example 15, Example 16, and Right: Example 17, Example 18

ContextMenuView tests, Left: Test 1, and Right: Test 2

ContextMenuView tests, Left: Test 3, and Right: Test 4

ContextMenuView tests, Left: Test 5, and Right: Test 6

ContextMenuView tests, Left/Right: Test 7

ContextMenuView ActionSheetIOS fallback for simple example 1 to 9

ContextMenuView ActionSheetIOS fallback for context menu view test 1 to 6

ContextMenuButton examples, Left: Example 1, and Right: Example 2

A.2. Feautures
- Support for creating menu actions and submenus (i.e. nested and in-line menus)
- Support for customizing the menu icons (i.e. support for SF Symbols,
require(image), andxcasseticons, icon tint, etc.) - Support for iOS 14 functionality (like the
UIButtoncontext menu, updating the menu while its visible, etc.) - Support for setting (almost) all of the native
UIMenuand UIActionproperties (e.g.UIMenuElementState,MenuElementAtrributes,discoverabilityTitle, etc.) - Basic
ActionSheetIOSmenu fallback for iOS 12 and below. - Support for creating custom context menu previews (with support for dynamic or fixed preview sizes, setting the
UIPreviewParameters, specifying aUITargetedPreview, etc.)
B. Installation
# 1A) install via NPM
npm install react-native-ios-context-menu
# 1B) or install via yarn
yarn add react-native-ios-context-menu
# 2) then run pod install (uses auto-linking)
cd ios && pod install
📝 Note: You will encounter some build errors since this library is written in swift, so there's some extra step involved to use this library (see table below for reference).
| Additional Steps |
|---|
| 1️⃣ Add an empty swift file to your project |
| 2️⃣ Update the project's "Library Search Paths" build settings |
Troubleshooting
If you encounter any errors/bugs while using this library, or want a particular feature implemented, please create an issue! ✨
Troubleshooting: Xcode Build Error (Swift)
📝 Note: This library is written in swift. If you are having trouble building your app after installing this library, try adding an empty swift file to your project:
- Open up your
ios/project.xcworkspaceproject - On the project navigator panel (located on the right side of Xcode), right click on your project group (or another folder/group i.e the blue or yellow icons) and select the "New File..." option
- In the popup sheet, select "Swift" as the template and then click the "Next" button
- A "Save As" popup sheet should appear and then click "Create" (you can rename the file first if you want to)
- If Xcode asks you to create a "Objective-C Bridging Header" choose "Create Objective-C Bridging Header"
Troubleshooting: Xcode Build Error (Undefined symbol)
When installing this library on Xcode 12+, you'll get the following error in Xcode:
Undefined symbol: (extension in UIKit):
__C.UIMenu.init(title: Swift.String, image: __C.UIImage?, identifier: __C.UIMenuIdentifier?, options: __C.UIMenuOptions, children: [__C.UIMenuElement]) -> __C.UIMenu
Undefined symbol: (extension in UIKit):
__C.UIAction.init(title: Swift.String, image: __C.UIImage?, identifier: __C.UIActionIdentifier?, discoverabilityTitle: Swift.String?, attributes: __C.UIMenuElementAttributes, state: __C.UIMenuElementState, handler: (__C.UIAction) -> ()) -> __C.UIAction
To fix this, see screenshot + follow the steps below:
- Open your
ios/project.xcworkspaceproject. - In the project navigator panel (located on the right side of Xcode), select your project group (i.e. the item with the blueprint icon).
- The Xcode project editor should appear. In the left panel, under the "Project" section, select your project (if it isn't already selected).
- In the project section's top tab bar, select the "Build Settings" tab (also make sure the "All" and "Combined" tabs are selected).
- In the project navigator list, under the "Search Path" section, there should be a "Library Search Paths" setting (alternatively, you can search for "Library Search Paths" in the search bar).
- According to this issue comment, you can clear all the items listed in the "Library Search Paths" setting by selecting the items in the list, and pressing the "-" button in the popover.
- TLDR: Xcode automatically manages this setting, and the RN template hardcodes it to use Swift 5.0.
- Alternatively, you can change the entry
"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)"to"$(TOOLCHAIN_DIR)/usr/lib/swift-5.3/$(PLATFORM_NAME)"i.e. changeswift-5.0toswift-5.3, or whatever the newest version of swift that comes with your Xcode installation (to show the popup dialog, double click the value/item).
- If you haven't already, make sure to create an empty swift file. Then clean the build folder (the option is in the menu bar under: "Product" -> "Clean Build Folder") and try building your project again.
- If you are still having problems building the app, try the following and build your project again:
- Try clearing out Xcode's
derivedDatadirectory:rm -rf ~/Library/Developer/Xcode/DerivedData/*(check out this gist for instructions on how to clean up Xcode) - Try clearing out the
Cocoapodscache:rm -rf "${HOME}/Library/Caches/CocoaPods"(and then try runningpod installagain).
Explanation: Some versions of the react-native template hard codes the swift library search paths to use swift 5.0 (which causes the linker to mismatch the swift system libraries bundled with your Xcode + iOS/Simulator installation).
Here are some related issues in the RN repo: Issue 30202 and Issue 29178.
C. Basic Usage
For more examples, check out the Usage And Examples section.
import * as React from 'react';
import { StyleSheet, Text } from 'react-native';
import { ContextMenuView } from 'react-native-ios-context-menu';
export function BasicUsageExample01() {
return (
<ContextMenuView
style={styles.container}
menuConfig={{
menuTitle: 'BasicUsageExample01',
menuItems: [{
actionKey : 'key-01',
actionTitle: 'Action #1',
}, {
actionKey : 'key-02' ,
actionTitle: 'Action #2',
}, {
actionKey : 'key-03' ,
actionTitle: 'Action #3',
}],
}}
>
<Text style={styles.text}>
Press And Hold To Show Context Menu
</Text>
</ContextMenuView>
);
};
const styles = StyleSheet.create({
container: {
margin: 10,
padding: 10,
},
text: {
fontSize: 16,
},
});
D. Documentation
💡 Tip: Most of the time, when a type or component is mentioned, you can click it to jump to that item in the README (or its declaration in the source code).
D.1. Components
ContextMenuView Component
ContextMenuView Component: Props
| Prop Name and Type | Description |
|---|---|
⚛️ ViewProps |
This component supports all the standard props from a <View/> component. |
🔤 menuConfig⚛️ MenuConfig |
TBA |
🔤 previewConfig⚛️ MenuPreviewConfig |
TBA |
🔤 shouldUseDiscoverabilityTitleAsFallbackValueForSubtitle⚛️ abc✳️ Default: true |
TBA |
🔤 isContextMenuEnabled⚛️ abc✳️ Default: true |
TBA |
🔤 lazyPreview⚛️ boolean✳️ Default: true |
TBA |
🔤 useActionSheetFallback⚛️ boolean✳️ Default: true |
TBA |
🔤 renderPreview⚛️ abc |
TBA |
ContextMenuView Component: Event Props
| Prop Name and Type | Description |
|---|---|
🔤 abc⚛️ abc |
TBA |
ContextMenuView Component: Properties/Methods
| Prop Name and Type | Description |
|---|---|
🔤 abc⚛️ abc |
TBA |
ContextMenuButton Component
ContextMenuButton Component: Props
| Prop Name and Type | Description |
|---|---|
⚛️ ViewProps |
This component supports all the standard props from a <View/> component. |
🔤 Required: abc⚛️ abc |
TBA |
🔤 abc⚛️ abc |
TBA |
ContextMenuButton Component: Event Props
| Prop Name and Type | Description |
|---|---|
🔤 abc⚛️ abc |
TBA |
ContextMenuButton Component: Properties/Methods
| Prop Name and Type | Description |
|---|---|
🔤 abc⚛️ abc |
TBA |
D.2. Context
TBA
D.3. Hooks
TBA
D.4. Objects and Types
📄 MenuConfig.ts
- 📌 Declaration:
MenuConfig.ts
Object Type: MenuConfig
| Name and Type | Description |
|---|---|
🔤 abc⚛️ abc |
TBA |
Object Type: MenuActionConfig
| Name and Type | Description |
|---|---|
🔤 abc⚛️ abc |
TBA |
String Union: MenuAttributes
| Type | Description |
|---|---|
🔤 abc |
TBA |
String Union: MenuState
| Type | Description |
|---|---|
🔤 abc⚛️ abc |
TBA |
String Union: UIMenuOptions
| Type | Description |
|---|---|
🔤 abc⚛️ abc |
TBA |
String Union: abc
| Type | Description |
|---|---|
🔤 abc⚛️ abc |
TBA |
📄 MenuPreviewConfig.ts
- 📌 Declaration:
MenuPreviewConfig.ts
Object Type: MenuPreviewConfig
| Name and Type | Description |
|---|---|
🔤 abc⚛️ abc |
TBA |
String Union: ContextMenuInteractionCommitStyle
| Name and Type | Description |
|---|---|
🔤 abc⚛️ abc |
TBA |
String Union: MenuPreviewSize
| Name and Type | Description |
|---|---|
🔤 abc⚛️ abc |
TBA |
String Union: MenuPreviewType
| Name and Type | Description |
|---|---|
🔤 abc⚛️ abc |
TBA |
📄 MenuIconConfig.ts
- 📌 Declaration:
MenuIconConfig.ts
Object Type: IconConfig
This has been deprecated and will be removed in a future version. Use ImageItemConfig instead.
| Name and Type | Description |
|---|---|
🔤 abc⚛️ abc |
TBA |
📄 ImageItemConfig.ts
- 📌 Declaration:
ImageItemConfig.ts
Object Type: ImageItemConfig
This type is an object tagged union type, with the type property being the tag that separates the unions. The table below defines the possible valid values that can be assigned to the type property.
| Name and Type | Description |
|---|---|
🔤 Required: type⚛️ ImageItemConfigType string union, i.e. 'IMAGE_ASSET' ¦ 'IMAGE_SYSTEM' ¦ 'IMAGE_REQUIRE' ¦ 'IMAGE_EMPTY' ¦ 'IMAGE_RECT' ¦ 'IMAGE_GRADIENT' |
TBA |
ImageItemConfig: IMAGE_ASSET
| Name and Type | Description |
|---|---|
🔤 Required: type⚛️ string i.e. 'IMAGE_ASSET' |
TBA 📌 Maps to UIImage.init(named:) constructor in the apple docs. |
🔤 Required: imageValue⚛️ string |
TBA |
🔤 imageOptions?⚛️ UIImageConfig |
TBA |
ImageItemConfig: IMAGE_SYSTEM
| Name and Type | Description |
|---|---|
🔤 Required: type⚛️ string i.e. 'IMAGE_SYSTEM' |
TBA 📌 Maps to UIImage.init(systemName:withConfiguration:) constructor in the apple docs. |
🔤 Required: imageValue⚛️ ImageSystemConfig |
TBA 📌 Maps to the withConfiguration argument label in the UIImage.init(systemName:withConfiguration:) constructor in the apple docs. |
🔤 imageOptions?⚛️ UIImageConfig |
TBA |
ImageItemConfig: IMAGE_EMPTY
| Name and Type | Description |
|---|---|
🔤 Required: type⚛️ string i.e. 'IMAGE_EMPTY' |
TBA |
ImageItemConfig: IMAGE_RECT
| Name and Type | Description |
|---|---|
🔤 Required: type⚛️ string i.e. 'IMAGE_RECT' |
TBA 📝 Note: Programmatically creates an image using UIGraphicsImageRenderer. |
🔤 Required: imageValue⚛️ ImageRectConfig |
TBA |
ImageItemConfig: IMAGE_GRADIENT
| Name and Type | Description |
|---|---|
🔤 Required: type⚛️ string i.e. 'IMAGE_GRADIENT' |
TBA 📝 Note: Programmatically creates an image using UIGraphicsImageRenderer. |
🔤 imageValue⚛️ ImageGradientConfig |
TBA |
Object Type: ImageResolvedAssetSource
TBA
| Name and Type | Description |
|---|---|
🔤 height⚛️ number |
TBA |
🔤 width⚛️ number |
TBA |
🔤 scale⚛️ number |
TBA |
🔤 uri⚛️ string |
TBA |
Object Type: ImageRectConfig
TBA
| Name and Type | Description |
|---|---|
🔤 Required: width⚛️ number |
TBA |
🔤 Required: height⚛️ number |
TBA |
🔤 Required: fillColor⚛️ string |
TBA |
🔤 borderRadius?⚛️ number |
TBA |
Object Type: ImageGradientConfig
TBA
| Name and Type | Description |
|---|---|
🔤 Required: width⚛️ number |
TBA |
🔤 Required: height⚛️ number |
TBA |
🔤 borderRadius?⚛️ number |
TBA |
🔤 Required: colors⚛️ Array<string> |
TBA 📌 Maps to CAGradientLayer.colors property in the apple docs. |
🔤 locations?⚛️ Array<number> |
TBA 📌 Maps to CAGradientLayer.locations property in the apple docs. |
🔤 startPoint?⚛️ Point ¦ PointPreset📌 Point📌 PointPreset |
TBA 📌 Maps to CAGradientLayer.startPoint property in the apple docs. |
🔤 endPoint?⚛️ Point ¦ PointPreset📌 Point📌 PointPreset |
TBA 📌 Maps to CAGradientLayer.endPoint property in the apple docs. |
🔤 type?⚛️ string i.e. 'axial' ¦ 'conic' ¦ 'radial' |
TBA 📌 Maps to CAGradientLayer.type property in the apple docs. |
Object Type: ImageSystemConfig
TBA
| Name and Type | Description |
|---|---|
🔤 Required: systemName⚛️ string |
TBA 📌 Maps to the systemName argument label in the UIImage.init(systemName:withConfiguration:) constructor in the apple docs. |
🔤 pointSize?⚛️ number |
TBA 📌 Maps to UIImage.SymbolConfiguration.init(pointSize:) constructor in the apple docs. |
🔤 weight?⚛️ ImageSymbolWeight |
TBA 📌 Maps to UIImage.SymbolConfiguration.init(weight:) constructor in the apple docs. |
🔤 scale?⚛️ ImageSymbolScale |
TBA 📌 Maps to UIImage.SymbolConfiguration.init(scale:) constructor in the apple docs. |
🔤 hierarchicalColor?⚛️ Array<string> |
TBA 📝 Note A: Cannot be used at the same time with paletteColors (it's either one or the other).📝 Note B: Requires iOS 15+. 📌 Maps to UIImage.SymbolConfiguration.init(hierarchicalColor:) constructor in the apple docs. |
🔤 paletteColors?⚛️ string |
TBA 📝 Note A: Cannot be used at the same time with hierarchicalColor (it's either one or the other).📝 Note B: Requires iOS 15+. 📌 Maps to UIImage.SymbolConfiguration.init(paletteColors:) constructor in the apple docs. |
Undocumented Types
TBA
| Type | Description |
|---|---|
📌 Declaration: MenuEvents |
This file contains all the menu-related events and event objects. |
📌 Declaration: MiscTypes.ts |
This file contains a bunch of types that haven't been categorized yet. Contains: PointPreset, Point, DynamicColor, etc. |
D.5. Constants
TBA
E. Usage And Examples
ContextMenuView Example 01
A basic context menu that has 3 menu action items (e.g. "Action #1", "Action #2", and "Action #3").
-
The
ContextMenuView.menuConfigprop accepts an optionalMenuConfigobject.- You can set the context menu title via the
MenuConfig.menuTitleproperty. - To populate the context menu with items, you can pass a
MenuActionConfigobject to theMenuConfig.menuItemsproperty. - A
MenuActionConfigobject represents an action item in the context menu (e.g. copy, paste, delete, etc).- The
MenuActionConfig.actionKeyproperty serves as a unique identifier for your menu action.- You will receive the value you passed in
MenuActionConfig.actionKeyin theContextMenuView.onPressMenuItemevent (i.e. via thenativeEventobject). - In other words, the
actionKeyallows you to identify which menu action item was selected/pressed. - 📝 Note: Make sure that the
actionKeyis unique for each instance of theContextMenuViewcomponent.
- You will receive the value you passed in
- The
- You can set the context menu title via the
-
You can use the
ContextMenuView.onPressMenuItemevent prop to get notified whenever a menu action item has been selected.- The function you pass to the
onPressMenuItemprop receives aOnPressMenuItemEventObjectobject. - Details about the selected menu action item can be accessed via the
OnPressMenuItemEventObject.nativeEventobject.- E.g.
OnPressMenuItemEventObject.nativeEvent.actionKey.
- E.g.
- The function you pass to the
// 📝 Note: for the sake of brevity, some of the code is omitted...
import { ContextMenuView } from 'react-native-ios-context-menu';
export function ContextMenuViewExample01(props) {
return (
<ContextMenuView
menuConfig={{
menuTitle: 'ContextMenuViewExample01',
menuItems: [{
actionKey : 'key-01',
actionTitle: 'Action #1',
}, {
actionKey : 'key-02' ,
actionTitle: 'Action #2',
}, {
actionKey : 'key-03' ,
actionTitle: 'Action #3',
}],
}}
onPressMenuItem={({nativeEvent}) => {
Alert.alert(
'onPressMenuItem Event',
`actionKey: ${nativeEvent.actionKey} - actionTitle: ${nativeEvent.actionTitle}`
);
}}
>
{/** Components */}
</ContextMenuView>
);
};
ContextMenuView Example 02
A basic context menu that has 3 menu action items, each with a different "SF Symbols" icon.
-
A
MenuActionConfigobject can be configured to show an icon via theMenuActionConfig.iconproperty.-
The
iconproperty accepts aImageItemConfigobject.- A
ImageItemConfigobject is used to describe images/assets (e.g. SF Symbols icons, images, xcasset images, programmatic images, etc).
- A
-
In this example, we want to use a "SF Symbols" icon for the menu action.
-
In order to do this, the
ImageItemConfig.typeproperty must be set to"IMAGE_SYSTEM".- Passing in a value of
"IMAGE_SYSTEM"to thetypeproperty means that we want to create a "SF Symbols" system icon. - Using a "SF Symbols" icon requires iOS 13+.
- Passing in a value of
-
In order to configure what kind of "SF Symbols" icon we want to use for the menu action, we need to pass in a
ImageSystemConfigobject to theImageItemConfig.imageValueproperty.- We set what kind of icon to use via passing a string value to the
ImageSystemConfig.systemNameproperty. - The string value passed to the
systemNameproperty must be a valid SF Symbols name.- To view the list of SF Symbols icons (along with their corresponding icon names), you'll need to download the SF Symbols Mac app from this page.
- We set what kind of icon to use via passing a string value to the
-
-
// 📝 Note: for the sake of brevity, some of the code is omitted...
import { ContextMenuView } from 'react-native-ios-context-menu';
export function ContextMenuViewExample02(props) {
return (
<ContextMenuView
menuConfig={{
menuTitle: 'ContextMenuViewExample02',
menuItems: [{
actionKey : 'key-01',
actionTitle: 'Action #1',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'folder',
},
}
}, {
actionKey : 'key-02' ,
actionTitle: 'Action #2',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'dial.fill',
},
}
}, {
actionKey : 'key-03' ,
actionTitle: 'Action #3',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'archivebox.fill',
},
}
}],
}}
>
{/** Components */}
</ContextMenuView>
);
};
ContextMenuView Example 03
This example shows a context menu that has a submenu item inside its list of menu actions.
-
A context menu supports having nested menu's (i.e. submenu's).
- A submenu is basically just another menu with it's own list separate list of menu actions.
- Tapping/selecting a submenu will show another context menu,
-
The
MenuConfig.menuItemsproperty can accept aMenuActionConfigobject, or aMenuConfigobject.- Passing in a
MenuActionConfigobject toMenuConfig.menuItemsmakes a menu action, conversely passing in aMenuConfigobject will create a submenu item. - In other words, to make a submenu, you just need to pass a
MenuConfigitem in theMenuConfig.menuItemsproperty.- 📝 Note: You can nest as many submenu's you want (but just remember that having more than 3 nested submenus is considered bad UX).
- Passing in a
// 📝 Note: for the sake of brevity, some of the code is omitted...
import { ContextMenuView } from 'react-native-ios-context-menu';
export function ContextMenuViewExample03(props) {
return (
<ContextMenuView
menuConfig={{
menuTitle: 'ContextMenuViewExample03',
menuItems: [{
actionKey : 'key-01',
actionTitle: 'Action #1',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'folder',
},
}
}, {
menuTitle: 'Submenu...',
menuItems: [{
actionKey : 'key-01-01',
actionTitle: 'Submenu Action #1',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'star',
},
}
}, {
actionKey : 'key-01-02',
actionTitle: 'Submenu Action #2',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'star.lefthalf.fill',
},
}
}, {
actionKey : 'key-01-03',
actionTitle: 'Submenu Action #3',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'star.fill',
},
}
}]
}],
}}
>
{/** Components */}
</ContextMenuView>
);
};
ContextMenuView Example 04
This example context menu showcases the MenuActionConfig.menuAttributes property.
-
The
MenuActionConfig.menuAttributesproperty accepts an array of string (i.e. an array ofMenuAttributesitems), -
This submenu has 3 actions:
- The first menu action is a "disabled" action. It has it's
menuAttributesset to[disabled].- The action title text and icon becomes grey out.
- The second menu action is a destructive action. It has it's
menuAttributesset to[destructive].- The action title text and icon becomes red.
- The third menu action is a "hidden" action. It has it's
menuAttributesset to[hidden].- The menu action is not visible in the menu's list of actions. This is useful for temporarily hiding a menu action item.
- The fourth menu action is a "disabled" + "destructive" action. Visually, it looks very similar to the
disabledaction.
- The first menu action is a "disabled" action. It has it's
// 📝 Note: for the sake of brevity, some of the code is omitted...
import { ContextMenuView } from 'react-native-ios-context-menu';
export function ContextMenuViewExample04(props) {
return (
<ContextMenuView
menuConfig={{
menuTitle: 'ContextMenuViewExample04',
menuItems: [{
actionKey : 'key-01',
actionTitle : 'Disabled Action',
menuAttributes: ['disabled'],
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'folder',
},
}
}, {
actionKey : 'key-02' ,
actionTitle : 'Destructive Action',
menuAttributes: ['destructive'],
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'trash',
},
}
}, {
actionKey : 'key-03' ,
actionTitle : 'Hidden Action',
menuAttributes: ['hidden'],
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'trash',
},
}
}, {
actionKey : 'key-04' ,
actionTitle : 'Disabled/Destructive',
menuAttributes: ['disabled', 'destructive'],
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'trash.fill',
},
}
}],
}}
>
{/** Components */}
</ContextMenuView>
);
};
ContextMenuView Example 05
// 📝 Note: for the sake of brevity, some of the code is omitted...
import { ContextMenuView } from 'react-native-ios-context-menu';
export function ContextMenuViewExample05(props) {
return (
<ContextMenuView
menuConfig={{
menuTitle: 'ContextMenuViewExample03',
menuItems: [{
actionKey : 'key-01',
actionTitle: 'Action #1',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'folder',
},
}
}, {
menuTitle: 'Submenu...',
menuOptions: ['displayInline'],
menuItems: [{
actionKey : 'key-01-01',
actionTitle: 'Submenu Action #1',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'star',
},
}
}, {
actionKey : 'key-01-02',
actionTitle: 'Submenu Action #2',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'star.lefthalf.fill',
},
}
}, {
actionKey : 'key-01-03',
actionTitle: 'Submenu Action #3',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'star.fill',
},
}
}]
}],
}}
>
{/** Components */}
</ContextMenuView>
);
};
ContextMenuView Example 06
// 📝 Note: for the sake of brevity, some of the code is omitted...
import { ContextMenuView } from 'react-native-ios-context-menu';
export function ContextMenuViewExample06(props) {
return (
<ContextMenuView
menuConfig={{
menuTitle: 'ContextMenuViewExample06',
menuItems: [{
actionKey : 'key-01',
actionTitle: 'Action #1',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'folder',
},
}
}, {
menuTitle: 'Submenu...',
menuOptions: ['destructive'],
menuItems: [{
actionKey : 'key-01-01',
actionTitle: 'Submenu Action #1',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'star',
},
}
}, {
actionKey : 'key-01-02',
actionTitle: 'Submenu Action #2',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'star.lefthalf.fill',
},
}
}, {
actionKey : 'key-01-03',
actionTitle: 'Submenu Action #3',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'star.fill',
},
}
}]
}],
}}
>
{/** Components */}
</ContextMenuView>
);
};
ContextMenuView Example 07
// 📝 Note: for the sake of brevity, some of the code is omitted...
import { ContextMenuView } from 'react-native-ios-context-menu';
export function ContextMenuViewExample07(props) {
return (
<ContextMenuView
menuConfig={{
menuTitle: 'ContextMenuViewExample07',
menuItems: [{
actionKey : 'key-01',
actionTitle: 'Action #1',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'folder',
},
}
}, {
menuTitle: 'Submenu...',
menuOptions: ['displayInline', 'destructive'],
menuItems: [{
actionKey : 'key-01-01',
actionTitle: 'Submenu Action #1',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'star',
},
}
}, {
actionKey : 'key-01-02',
actionTitle: 'Submenu Action #2',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'star.lefthalf.fill',
},
}
}, {
actionKey : 'key-01-03',
actionTitle: 'Submenu Action #3',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'star.fill',
},
}
}]
}],
}}
>
{/** Components */}
</ContextMenuView>
);
};
ContextMenuView Example 08
// 📝 Note: for the sake of brevity, some of the code is omitted...
import { ContextMenuView } from 'react-native-ios-context-menu';
export function ContextMenuViewExample08(props) {
return (
<ContextMenuView
menuConfig={{
menuTitle: 'ContextMenuViewExample08',
menuItems: [{
actionKey : 'key-01',
actionTitle: 'menuState: on',
menuState : 'on',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'folder',
},
}
}, {
actionKey : 'key-02' ,
actionTitle: 'menuState: off',
menuState : 'off',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'dial',
},
}
}, {
actionKey : 'key-03' ,
actionTitle: 'menuState: mixed',
menuState : 'mixed',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'archivebox',
},
}
}],
}}
>
{/** Components */}
</ContextMenuView>
);
};
ContextMenuView Example 09
// 📝 Note: for the sake of brevity, some of the code is omitted...
import { ContextMenuView } from 'react-native-ios-context-menu';
export function ContextMenuViewExample09(props) {
return (
<ContextMenuView
menuConfig={{
menuTitle: 'ContextMenuViewExample09',
menuItems: [{
actionKey : 'save',
actionTitle: 'Save',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'square.and.arrow.down',
},
}
}, {
actionKey : 'like',
actionTitle: 'Like',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'hand.thumbsup',
},
}
}, {
actionKey : 'play',
actionTitle: 'Play',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'play',
},
}
}],
}}
onPressMenuItem={({nativeEvent}) => {
switch (nativeEvent.actionKey) {
case 'save':
Alert.alert('saving...');
break;
case 'like':
Alert.alert('liking...');
break;
case 'play':
Alert.alert('playing...');
break;
};
}}
>
{/** Components */}
</ContextMenuView>
);
};
ContextMenuView Example 10
// 📝 Note: for the sake of brevity, some of the code is omitted...
import { ContextMenuView } from 'react-native-ios-context-menu';
export function ContextMenuViewExample10(props) {
const [timer, setTimer] = React.useState(0);
const increment = React.useRef(null);
const handleStart = () => {
increment.current = setInterval(() => {
setTimer((prevTimer) => prevTimer + 1);
}, 1000);
};
const handleReset = () => {
clearInterval(increment.current);
setTimer(0);
};
return (
<ContextMenuView
onMenuDidShow={() => handleStart()}
onMenuDidHide={() => handleReset()}
menuConfig={{
menuTitle: 'ContextMenuViewExample10',
menuItems: [{
actionKey : 'key-00',
actionTitle: `Static Action`,
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'square.and.arrow.down',
},
}
}, {
actionKey : 'key-01',
actionTitle: `timer: ${timer}`,
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: ((timer % 2 === 0)
? 'heart'
: 'heart.fill'
),
},
}
}, (timer % 3 === 0) && {
actionKey : 'key-02',
actionTitle: `Dynamic Action`,
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'scissors.badge.ellipsis',
},
}
}],
}}
>
{/** Components */}
</ContextMenuView>
);
};
ContextMenuView Example 11
// 📝 Note: for the sake of brevity, some of the code is omitted...
import { ContextMenuView } from 'react-native-ios-context-menu';
export function ContextMenuViewExample11(props) {
return (
<ContextMenuView
previewConfig={{
previewType: 'CUSTOM',
previewSize: 'STRETCH',
backgroundColor: 'white'
}}
renderPreview={() => (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text style={{fontSize: 32}}>
Hello World
</Text>
<Text style={{fontSize: 32}}>
Hello World
</Text>
<Text style={{fontSize: 32}}>
Hello World
</Text>
</View>
)}
onPressMenuPreview={() => {
Alert.alert(
'onPressMenuPreview Event',
`Menu preview was pressed...`
);
}}
>
{/** Components */}
</ContextMenuView>
);
};
ContextMenuView Example 12
// 📝 Note: for the sake of brevity, some of the code is omitted...
import { ContextMenuView } from 'react-native-ios-context-menu';
export function ContextMenuViewExample12(props) {
const [timer, setTimer] = React.useState(0);
const increment = React.useRef(null);
const handleStart = () => {
increment.current = setInterval(() => {
setTimer((prevTimer) => prevTimer + 1);
}, 1000);
};
const handleStop = () => {
clearInterval(increment.current);
};
const handleReset = () => {
clearInterval(increment.current);
setTimer(0);
};
return (
<ContextMenuView
menuConfig={{
menuTitle: 'ContextMenuViewExample12',
menuItems: [{
actionKey : 'add',
actionTitle : `Add 100`,
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'plus',
},
}
}, (timer > 0) && {
actionKey : 'reset',
actionTitle : `Reset Counter`,
menuAttributes: ['destructive'],
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'trash',
},
}
}],
}}
previewConfig={{
previewType: 'CUSTOM',
backgroundColor: 'white'
}}
renderPreview={() => (
<View style={{ padding: 20 }}>
<Text style={{fontSize: 32}}>
{`Counter: ${timer}`}
</Text>
<Text style={{fontSize: 32}}>
{(timer % 2 === 0)? 'EVEN' : 'The number is: ODD'}
</Text>
</View>
)}
onMenuDidShow={() => handleStart()}
onMenuDidHide={() => handleStop()}
onPressMenuItem={({nativeEvent}) => {
switch (nativeEvent.actionKey) {
case 'add':
setTimer((prevTimer) => prevTimer + 100);
break;
case 'reset':
handleReset();
break;
};
}}
>
{/** Components */}
</ContextMenuView>
);
};
ContextMenuView Example 13
// 📝 Note: for the sake of brevity, some of the code is omitted...
import { ContextMenuView } from 'react-native-ios-context-menu';
export function ContextMenuViewExample13(props) {
return (
<ContextMenuView
menuConfig={{
menuTitle: 'ContextMenuViewExample13',
menuItems: [{
actionKey: 'key-01',
actionTitle: 'Action #1',
// iOS 13 to 14 (still works on iOS 15+)
actionSubtitle: 'Action subtitle',
}, {
actionKey: 'key-02' ,
actionTitle: 'Action #2',
// iOS 15+ only
actionSubtitle: 'Lorum ipsum sit amit dolor aspicing',
}, {
actionKey: 'key-03' ,
actionTitle: 'Action #3',
actionSubtitle: 'Very long `discoverabilityTitle` lorum ipsum sit amit',
}],
}}
>
{/** Components */}
</ContextMenuView>
);
};
ContextMenuView Example 14
// 📝 Note: for the sake of brevity, some of the code is omitted...
import { ContextMenuView } from 'react-native-ios-context-menu';
export function ContextMenuViewExample14(props) {
return (
<ContextMenuView
previewConfig={{
previewType: 'CUSTOM',
previewSize: 'STRETCH',
backgroundColor: 'rgba(255,255,255,0.75)',
preferredCommitStyle: 'pop',
}}
renderPreview={() => (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text style={{fontSize: 32}}>
Hello World
</Text>
<Text style={{fontSize: 32}}>
Hello World
</Text>
<Text style={{fontSize: 32}}>
Hello World
</Text>
</View>
)}
>
{/** Components */}
</ContextMenuView>
);
};
ContextMenuView Example 15
// 📝 Note: for the sake of brevity, some of the code is omitted...
import { ContextMenuView } from 'react-native-ios-context-menu';
export function ContextMenuViewExample15(props) {
const [targetViewNode, setTargetViewNode] = React.useState(null);
const viewRef = React.useRef();
React.useEffect(() => {
setTargetViewNode(
findNodeHandle(viewRef.current)
);
}, []);
return (
<ContextMenuView
menuConfig={{
menuTitle: 'ContextMenuViewExample15',
menuItems: [{
actionKey : 'key-01',
actionTitle: 'Action #1',
}],
}}
previewConfig={{
targetViewNode: targetViewNode,
}}
>
<View
style={styles.targetContainer}
ref={viewRef}
>
<Text style={styles.text}>
{`Hello! Target Node: ${targetViewNode}`}
</Text>
</View>
</ContextMenuView>
);
};
const styles = StyleSheet.create({
targetContainer: {
backgroundColor: 'rgba(255,255,255,0.5)',
alignSelf: 'flex-start',
padding: 10,
borderRadius: 10,
marginTop: 10,
},
text: {
fontSize: 16,
}
});
ContextMenuView Example 16
// 📝 Note: for the sake of brevity, some of the code is omitted...
import { ContextMenuView } from 'react-native-ios-context-menu';
export function ContextMenuViewExample16(props) {
return (
<ContextMenuView
menuConfig={{
menuTitle: 'ContextMenuViewExample16',
menuItems: [{
actionKey : 'key-01',
actionTitle: 'Action #1',
discoverabilityTitle: 'No Icon',
}, {
actionKey : 'key-02' ,
actionTitle: 'Action #2',
discoverabilityTitle: 'Use "IMAGE_SYSTEM" icon',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'dial.fill',
},
}
}, {
actionKey : 'key-03' ,
actionTitle: 'Action #3',
discoverabilityTitle: 'Use "ASSET" icon',
icon: {
type: 'IMAGE_ASSET',
imageValue: 'icon-rainbow-flag',
}
}],
}}
>
{/** Components */}
</ContextMenuView>
);
};
ContextMenuView Example 17
// 📝 Note: for the sake of brevity, some of the code is omitted...
import { ContextMenuView } from 'react-native-ios-context-menu';
export function ContextMenuViewExample17(props) {
return (
<ContextMenuView
menuConfig={{
menuTitle: 'ContextMenuViewExample17',
menuItems: [{
actionKey : 'key-01',
actionTitle: 'Action #1',
discoverabilityTitle: 'Blue Icon',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'cloud.heavyrain.fill',
},
imageOptions: {
tint: 'blue',
renderingMode: 'alwaysOriginal',
},
},
}, {
actionKey : 'key-02',
actionTitle: 'Action #2',
discoverabilityTitle: 'Orange Icon',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'exclamationmark.triangle.fill',
},
imageOptions: {
tint: 'rgb(218,165,32)',
renderingMode: 'alwaysOriginal',
},
},
}, {
actionKey : 'key-03',
actionTitle: 'Action #3',
discoverabilityTitle: 'Pink Icon',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'heart.fill',
},
imageOptions: {
tint: '#FF1493',
renderingMode: 'alwaysOriginal',
},
},
}, {
actionKey : 'key-04',
actionTitle: 'Action #4',
discoverabilityTitle: 'Green Icon',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'bubble.right.fill',
},
imageOptions: {
tint: 'rgba(124,252,0,0.5)',
renderingMode: 'alwaysOriginal',
},
},
}]
}}
>
{/** Components */}
</ContextMenuView>
);
};
ContextMenuView Example 18
// 📝 Note: for the sake of brevity, some of the code is omitted...
import { ContextMenuView } from 'react-native-ios-context-menu';
const iconA = Image.resolveAssetSource(
require('../assets/emoji-pleading-face.png')
);
const iconB = Image.resolveAssetSource(
require('../assets/emoji-smiling-face-with-hearts.png')
);
const iconC = Image.resolveAssetSource(
require('../assets/emoji-sparkling-heart.png')
);
export function ContextMenuViewExample18(props) {
return (
<ContextMenuView
menuConfig={{
menuTitle: 'ContextMenuViewExample18',
menuItems: [{
actionKey : 'key-01' ,
actionTitle: 'Action #1',
discoverabilityTitle: 'Use "REQUIRE" icon',
// `IconConfig` has been deprecated, please use
// `ImageItemConfig` instead (but it'll still work for now).
//
// The other two menu actions in this example
// uses `ImageItemConfig` to set the menu action icons.
icon: {
iconType: 'REQUIRE',
iconValue: iconA,
}
}, {
actionKey : 'key-02' ,
actionTitle: 'Action #2',
discoverabilityTitle: 'Use "IMAGE_REQUIRE" icon',
icon: {
type: 'IMAGE_REQUIRE',
imageValue: iconB,
}
}, {
actionKey : 'key-03' ,
actionTitle: 'Action #3',
discoverabilityTitle: 'Use "IMAGE_REQUIRE" icon',
icon: {
type: 'IMAGE_REQUIRE',
imageValue: iconC,
}
}],
}}
>
{/** Components */}
</ContextMenuView>
);
};
ContextMenuButton Example 01
// 📝 Note: for the sake of brevity, some of the code is omitted...
import { ContextMenuButton } from 'react-native-ios-context-menu';
export function ContextMenuButtonExample01() {
return (
<ContextMenuButton
menuConfig={{
menuTitle: 'ContextMenuButtonSimpleExample01',
menuItems: [{
actionKey : 'key-01',
actionTitle: 'Action #1',
}, {
actionKey : 'key-02' ,
actionTitle: 'Action #2',
}, {
actionKey : 'key-03' ,
actionTitle: 'Action #3',
}],
}}
onPressMenuItem={({nativeEvent}) => {
Alert.alert(
'onPressMenuItem Event',
`actionKey: ${nativeEvent.actionKey} - actionTitle: ${nativeEvent.actionTitle}`
);
}}
>
{/** Components */}
</ContextMenuButton>
);
};
ContextMenuButton Example 02
// 📝 Note: for the sake of brevity, some of the code is omitted...
import { ContextMenuButton } from 'react-native-ios-context-menu';
export function ContextMenuButtonExample02(props) {
return (
<ContextMenuButton
isMenuPrimaryAction={true}
menuConfig={{
menuTitle: 'ContextMenuButtonSimpleExample02',
menuItems: [{
actionKey : 'key-01',
actionTitle: 'Action #1',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'folder',
},
}
}, {
actionKey : 'key-02' ,
actionTitle: 'Action #2',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'dial.fill',
},
}
}, {
actionKey : 'key-03' ,
actionTitle: 'Action #3',
icon: {
type: 'IMAGE_SYSTEM',
imageValue: {
systemName: 'archivebox.fill',
},
}
}],
}}
onPressMenuItem={({nativeEvent}) => {
Alert.alert(
'onPressMenuItem Event',
`actionKey: ${nativeEvent.actionKey} - actionTitle: ${nativeEvent.actionTitle}`
);
}}
>
{/** Components */}
</ContextMenuButton>
);
};
F. Showcase, Tests and Demos
G. Meta
H. Licence
MIT










































