[BREAKGLASS] Append-only mirror of github.com/bluewallet/react-native-ios-context-menu
Go to file
Dominic Go 83aecaf679 🛠 Refactor: Example - Rename ContextMenuViewExample22
Summary: Rename `ContextMenuViewExample22` to `ContextMenuViewExample23`
2022-06-20 00:47:22 +08:00
.github/workflows 💫 Update build-ios.yml 2021-11-27 17:24:41 +08:00
android 🛠 Updated Project Template 2021-11-12 05:17:14 +08:00
assets Delete Old Assets 2022-01-08 06:38:13 +08:00
docs 📝 Docs: Update TODO 2022-06-19 15:23:14 +08:00
example 🛠 Refactor: Example - Rename ContextMenuViewExample22 2022-06-20 00:47:22 +08:00
ios 🐞 Fix: Aux. Preview - previewCenter 2022-06-20 00:16:35 +08:00
scripts 🛠 Updated Project Template 2021-11-12 05:17:14 +08:00
src ️ Impl: Aux. Preview - isAuxiliaryPreviewEnabled 2022-06-19 14:51:21 +08:00
.editorconfig chore: initial commit 2020-10-21 11:58:36 +08:00
.gitattributes chore: initial commit 2020-10-21 11:58:36 +08:00
.gitignore Update .gitignore 2022-01-08 18:04:57 +08:00
.nvmrc 🆕 Create .nvmrc 2021-11-27 06:42:23 +08:00
.yarnrc 🛠 Updated Project Template 2021-11-12 05:17:14 +08:00
babel.config.js chore: initial commit 2020-10-21 11:58:36 +08:00
CONTRIBUTING.md 📝 Updated: CONTRIBUTING.md 2020-11-24 12:24:19 +08:00
LICENSE chore: initial commit 2020-10-21 11:58:36 +08:00
package.json ⚙️ chore: release 1.9.0 2022-06-19 15:25:14 +08:00
react-native-ios-context-menu.podspec ⚙️ Podfile: Set swift version to 5.3 2021-01-11 18:06:00 +08:00
react-native.config.js 💄 Fixed Linter Errors 2021-11-12 00:13:54 +08:00
README-old.md 📝 Use README-next as README 2022-01-08 06:35:55 +08:00
README.md 📝 Docs: Update README - Minor Changes 2022-06-19 20:36:59 +08:00
tsconfig.build.json 🛠 Updated TS Config 2021-11-12 00:13:14 +08:00
tsconfig.json 🛠 Updated TS Config 2021-11-12 00:13:14 +08:00
yarn.lock 📦 Package: Add @dominicstop/ts-event-emitter 2022-06-17 20:04:01 +08:00

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 Simple Example 1 to 4 Gifs

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

ContextMenuView example, Left: Example 9, and Right: Example 10 Simple Example 9 and 8 Gifs

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

ContextMenuView examples, Left: Example 15, Example 16, and Right: Example 17, Example 18 Simple Example 11 to 14 Gifs

ContextMenuView tests, Left: Test 1, and Right: Test 2 Context Menu View Test 1 and 2 Gifs

ContextMenuView tests, Left: Test 3, and Right: Test 4 Context Menu View Test 3 and 4 Gifs

ContextMenuView tests, Left: Test 5, and Right: Test 6 Context Menu View Test 5 and 6 Gifs

ContextMenuView tests, Left/Right: Test 7 Context Menu View 7 Gifs

ContextMenuView ActionSheetIOS fallback for simple example 1 to 9 Action Sheet Fallback for Simple Example 1 to 9 Gifs

ContextMenuView ActionSheetIOS fallback for context menu view test 1 to 6 Action Sheet Fallback for Context Menu View Test 1 to 6 Gifs

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


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), and xcasset icons, icon tint, etc.)
  • Support for iOS 14 functionality (like the UIButton context menu, updating the menu while its visible, etc.)
  • Support for setting (almost) all of the native UIMenu and UIAction properties (e.g. UIMenuElementState, MenuElementAtrributes, discoverabilityTitle, etc.)
  • Basic ActionSheetIOS menu 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 a UITargetedPreview, 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:

  1. Open up your ios/project.xcworkspace project
  2. 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
  3. In the popup sheet, select "Swift" as the template and then click the "Next" button
  4. A "Save As" popup sheet should appear and then click "Create" (you can rename the file first if you want to)
  5. 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:

Xcode linking build error

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:

Xcode - Remove library search paths


  1. Open your ios/project.xcworkspace project.
  2. In the project navigator panel (located on the right side of Xcode), select your project group (i.e. the item with the blueprint icon).
  3. The Xcode project editor should appear. In the left panel, under the "Project" section, select your project (if it isn't already selected).
  4. In the project section's top tab bar, select the "Build Settings" tab (also make sure the "All" and "Combined" tabs are selected).
  5. 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).
  6. 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. change swift-5.0 to swift-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).
  7. 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.
  8. If you are still having problems building the app, try the following and build your project again:
  • Try clearing out Xcode's derivedData directory: rm -rf ~/Library/Developer/Xcode/DerivedData/* (check out this gist for instructions on how to clean up Xcode)
  • Try clearing out the Cocoapods cache: rm -rf "${HOME}/Library/Caches/CocoaPods" (and then try running pod install again).

Xcode - Remove library search paths


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.


🔗 Full Example

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
Configures the context menu, along with what menu actions to show.

This prop accepts a MenuConfig object. This object is used to configure various aspects of the context menu:
MenuConfig.menuTitle: the context menu title (required),

MenuConfig.menuItems the actions to show (along with their title, icons, subtitle, etc) — Accepts either an array of MenuActionConfig or MenuConfig objects.,

MenuConfig.menuOptions: the attributes of the context menu (e.g. destructive) — Accepts an array of UIMenuOptions string items,

• and any nested menus or submenus to show (see "Note A").

📝 Note A: Passing a MenuConfig object inside of the MenuConfig.menuItems property will result in a nested context menu or submenu. In this scenario, the MenuConfig.menuOptions and MenuConfig.icon can be used to configure the appearance of the submenu. For usage examples regarding nested menus, see Example 06

📝 Note B: Passing a value of null (or undefined) to this prop will not disable the context menu. Use the isContextMenuEnabled prop instead to disable the context menu.

📝 Note C: You can put MenuConfig in state if you want to dynamically change the menu configuration. If the context menu is currently visible, changing/updating the MenuConfig value passed to this prop will cause the context menu to change in real-time. This behavior is only supported on iOS 14+.

📌 Some example links to get you started:
• For basic usage examples regarding MenuConfig, see: Example 1,

• For examples on creating + configuring the menu action items (i.e MenuActionConfig), see: Example 2,

• For menu action attributes + menu state, and action subtitles, see: Example 4, Example 8, and Example 13,

• For examples regarding the usage of icons (i.e ImageItemConfig), see: Example 16, Example 17, and Example 18.
🔤 previewConfig

⚛️ MenuPreviewConfig
Configures the context menu's preview.

If no configuration is provided then it will default to using the context menu component itself as the preview.

📝 Note: If you do not want to show a preview (i.e only show the context menu itself), consider using a ContextMenuButton component instead.

📌 Some example links to get you started:
• For examples regarding the configuration of the context menu preview (e.g. custom previews), see: Example 11, Example 12, Example 14, and Example 15.
🔤 shouldUseDiscoverability
TitleAsFallbackValueForSubtitle

⚛️ boolean

✳️ Default: true
On iOS 15+, the value passed to the MenuActionConfig.discoverabilityTitle property is no longer displayed as a subtitle under the menu action.

Instead you need to set a different property called MenuActionConfig.subtitle.

The discoverabilityTitle property is now used for the "discoverability heads-up display" (e.g when an app supports keyboard shortcuts, holding down the command key presents a list of shortcuts; the discoverabilityTitle is then used as the title for the shortcut).

If this prop is set to true, it will then uses the value passed on to the discoverabilityTitle value as the subtitle for the menu action, preserving the old behavior. In other words, this prop exists for backwards-compatibility reasons.

📝 Note: This prop is set to true by default; set this to false if you don't want this automatic behaviour to happen.
🔤 shouldWaitForMenuToHide
BeforeFiringOnPressMenuItem

⚛️ boolean

✳️ Default: true
If set to true, the onPressMenuItem event will be triggered after the context menu has been hidden (i.e. after onMenuDidHide event is triggered).

Set this to false if you want onPressMenuItem to trigger as soon as an item has been pressed in the context menu.

📝 Note: Layout updates while the context menu is transitioning from it's open to hidden state might cause layout flickering (e.g. Issue #43).
🔤 isContextMenuEnabled

⚛️ boolean

✳️ Default: true
Enables or disables the context menu. Useful if you want to temporarily disable the context menu.
🔤 lazyPreview

⚛️ boolean

✳️ Default: true
If set to true (which it is by default), the custom context menu preview (i.e the component returned from the ContextMenuView.renderPreview prop) will only be mounted/rendered when the context menu interaction begins (i.e when the context menu is about to be shown).

Set this to false if you want the preview content to be always mounted.
🔤 useActionSheetFallback

⚛️ boolean

✳️ Default: true
Context menus are only supported on iOS 13+ (i.e context menus are not supported on iOS 12, and below).

On iOS 12 and below, a long press on a ContextMenuView will show a ActionSheetIOS menu based on the current menuConfig prop.

If you want to disable this behavior, set this prop to false.

📝 Note: Default value is false on iOS 13+, and true on iOS 12 and below.
🔤 renderPreview

⚛️ () => React.ReactElement
This prop is a "render" prop, i.e it accepts a function that returns a react component.

The returned component will displayed in the context menu preview.
🔤 isAuxiliaryPreviewEnabled

⚛️ boolean

✳️ Default: false
⚠️ Experimental: Please see Auxiliary Preview section.

TBA
🔤 auxiliaryPreviewConfig

⚛️ MenuAuxiliaryPreviewConfig
⚠️ Experimental: Please see Auxiliary Preview section.

TBA
🔤 renderAuxillaryPreview

⚛️ () => React.ReactElement
⚠️ Experimental: Please see Auxiliary Preview section.

TBA

ContextMenuView Component: Event Props
Prop Name and Type Description
🔤 onMenuWillShow

⚛️ OnMenuWillShowEvent
Event that gets called before the context menu is shown, i.e this event is immediately invoked when the menu is about to become visible.
🔤 onMenuDidShow

⚛️ OnMenuDidShowEvent
Event that gets called after the context menu is shown, i.e this event is invoked after the menu entrance animation is finished.
🔤 onMenuWillHide

⚛️ OnMenuWillHideEvent
Event that gets called before the context menu is hidden, i.e this event is immediately invoked when the menu is about to become hidden.
🔤 onMenuDidHide

⚛️ OnMenuDidHideEvent
Event that gets called after the context menu is hidden, i.e this event is invoked after the menu exit animation is finished.
🔤 onMenuWillCancel

⚛️ OnMenuWillCancelEvent
Event that gets called when the menu is cancelled and about to be hidden, i.e this event is immediately invoked when the context menu interaction is cancelled.
🔤 onMenuDidCancel

⚛️ OnMenuDidCancelEvent
Event that gets called when the menu is cancelled and hidden, i.e. this event is invoked when the context menu is cancelled, and the menu exit transition is finished.
🔤 onPressMenuItem

⚛️ OnPressMenuItemEvent
Event that gets called when a menu action is pressed.

You can identify which action was pressed via nativeEvent.actionKey property in the nativeEvent object.

Check out Example 1, and Example 9 for examples regarding the onPressMenuItem event prop.

📝 Note: If shouldWaitForMenuToHide
BeforeFiringOnPressMenuItem prop is set to true (which it is by default), then this event will fire after onMenuDidHide is triggered.
🔤 onPressMenuPreview

⚛️ OnPressMenuPreviewEvent
Event that gets called when the menu's preview is pressed.
🔤 onMenuAuxiliaryPreviewWillShow

⚛️ OnMenuAuxiliaryPreviewWillShowEvent
⚠️ Experimental: Please see Auxiliary Preview section.

TBA
🔤 onMenuAuxiliaryPreviewDidShow

⚛️ OnMenuAuxiliaryPreviewDidShowEvent
⚠️ Experimental: Please see Auxiliary Preview section.

TBA

ContextMenuView Component: Properties/Methods
Prop Name and Type Description
🔤 dismissMenu

⚛️ Promise<Void>
Allows you to programmatically dismiss the context menu. Only available on iOS 14 and above.

ContextMenuView Component: Experimental - Auxiliary Preview

The context menu auxiliary preview is an experimental feature, and is not officially part of UIKit's "Menu and Shortcuts" API.

This is just a feature that I've implemented myself and added to the library — as such official support is limited and might break in a future iOS version. Please use at your own risk.


ContextMenuButton Component

For basic usage, please see Example 1 section.

  • The ContextMenuButton component is almost the same as the ContextMenuView component (It supports the same kind of props and events).

  • The only difference between them is that the ContextMenuButton component does not have a preview, and it can be immediately shown when its tapped instead of having to do a long press. See Example 2 for more details.

  • Note that ContextMenuButton is only available on iOS 14 and above. On iOS 13, it will use a ContextMenuButton, and on iOS 12 and below, it will use the ActionSheetFallback module to present a ActionSheetIOS menu.

  • If you want to add additional touch events, you can wrap this component inside a button component (e.g. TouchableOpacity).

    • When wrapping this component inside a button, please make sure to set the useActionSheetFallback prop to false.

ContextMenuButton Component: Props
Prop Name and Type Description
⚛️ ViewProps This component supports all the standard props from a <View/> component.
🔤 menuConfig

⚛️ MenuConfig
Same as ContextMenuView.menuConfig prop.
🔤 isMenuPrimaryAction

⚛️ boolean
When set to true, the context menu will be shown when its tapped instead of a long press.
🔤 shouldUseDiscoverability
TitleAsFallbackValueForSubtitle

⚛️ boolean

✳️ Default: true
TBA / Not Implented
🔤 enableContextMenu

⚛️ boolean

✳️ Default: true
Same as ContextMenuView.enableContextMenu prop.
🔤 useActionSheetFallback

⚛️ boolean

✳️ Default: true
Same as ContextMenuView.useActionSheetFallback prop.

ContextMenuButton Component: Event Props
Prop Name and Type Description
🔤 onMenuWillShow

⚛️ OnMenuWillShowEvent
Same as ContextMenuView.onMenuWillShow event.
🔤 onMenuDidShow

⚛️ OnMenuDidShowEvent
Same as ContextMenuView.onMenuDidShow event.
🔤 onMenuWillHide

⚛️ OnMenuWillHideEvent
Same as ContextMenuView.onMenuWillHide event.
🔤 onMenuDidHide

⚛️ OnMenuDidHideEvent
Same as ContextMenuView.onMenuDidHide event.
🔤 onMenuWillCancel

⚛️ OnMenuWillCancelEvent
Same as ContextMenuView.onMenuWillCancel event.
🔤 onMenuDidCancel

⚛️ OnMenuDidCancelEvent
Same as ContextMenuView.onMenuDidCancel event.
🔤 onMenuWillCreate

⚛️ OnMenuWillCreateEvent
Same as ContextMenuView.onMenuWillCreate event.
🔤 onPressMenuItem

⚛️ OnPressMenuItemEvent
Same as ContextMenuView.onPressMenuItem event.

ContextMenuButton Component: Properties/Methods
Prop Name and Type Description
🔤 dismissMenu

⚛️ Promise<Void>
Same as ContextMenuView.dismissMenu method.

ActionSheetFallback Module

A module to show a ActionSheetIOS menu based on a MenuConfig object.

This module attempts to approximate UIMenu behavior using ActionSheetIOS, so it's very limited (i.e. it does not support menu/action icons, etc.), but it does support things like submenu's, destructive actions/menu's, inline submenu's, and hidden actions.


  • Import the module like this: import { ActionSheetFallback } from "react-native-ios-context-menu";

  • To present a ActionSheetIOS menu, call const selectedAction = await ActionSheetFallback.show(menuConfig)


Function Description
🔤 show

⚛️ (menuConfig: MenuConfig):
Promise<MenuAction ¦ null>
This function accepts a MenuConfig object and returns the selected MenuAction object or null if cancelled.

D.2. Context

ContextMenuViewContext Context

TBA

Property Description
🔤 isMenuVisible

⚛️ boolean
TBA
🔤 getRefToContextMenuView

⚛️ () => ContextMenuView
📌 ContextMenuView
TBA

ContextMenuButtonContext Context

TBA

Property Description
🔤 isMenuVisible

⚛️ boolean
TBA
🔤 getRefToContextMenuButton

⚛️ () => ContextMenuView
📌 ContextMenuButton
TBA

D.3. Hooks

useMenuContext Hook

A hook to use the ContextMenuViewContext context.

TBA


useMenuButtonContext Hook

A hook to use the ContextMenuButtonContext context.

TBA


D.4. Objects and Types

📄 MenuConfig.ts

Object Type: MenuConfig

A container for grouping related menu elements in an app menu or contextual menu.

An object that is used to create and configure a context menu. Internally, this object is used to create a UIMenu instance (see apple docs for more information).


Name and Type Description
🔤 type

⚛️ string, i.e"menu"
TBA
🔤 menuTitle

⚛️ string
TBA

📝 Note: If you don't want a menu title to appear for your context menu, just pass in an empty string to this property.
🔤 menuOptions

⚛️ Array<UIMenuOptions>
📌 UIMenuOptions
TBA
🔤 menuItems

⚛️ Array<MenuConfig ¦ MenuActionConfig
📌 MenuConfig
📌 MenuActionConfig
TBA
🔤 icon

⚛️ IconConfig ¦ ImageItemConfig
📌 IconConfig (deprecated)
📌 ImageItemConfig
TBA

Object Type: MenuActionConfig

An object that is used to create a menu action item in the context menu. Internally, this object is used to create a UIAction instance (see apple docs for more information),


Name and Type Description
🔤 type

⚛️ string, i.e "action"
TBA
🔤 Required: actionKey

⚛️ string
TBA
🔤 Required: actionTitle

⚛️ string
TBA
🔤 actionSubtitle

⚛️ string
TBA
🔤 menuState

⚛️ MenuState
TBA
🔤 menuAttributes

⚛️ Array<MenuAttributes>
📌 MenuAtrributes
TBA
🔤 discoverabilityTitle

⚛️ string
TBA
🔤 icon

⚛️ IconConfig ¦ ImageItemConfig
📌 IconConfig (deprecated)
📌 ImageItemConfig
TBA

String Union: MenuAttributes

Attributes that determine the style of the menu element.

A union string type that maps to UIMenuElement.Attributes enum (see apple docs for more information).


Type Description
⚛️ hidden TBA
⚛️ disabled TBA
⚛️ destructive TBA

String Union: MenuState

Constants that indicate the state of an action- or command-based menu element.

A union string type that maps to UIMenuElement.State enum (see apple docs for more information).


Type Description
⚛️ on TBA
⚛️ off TBA
⚛️ mixed TBA

String Union: UIMenuOptions

Options for configuring a menu's appearance.

A union string type that maps to UIMenu.Options option set (see apple docs for more information).


Type Description
⚛️ destructive TBA
⚛️ displayInline TBA

📄 MenuPreviewConfig.ts

Object Type: MenuPreviewConfig
Name and Type Description
🔤 previewType

⚛️ MenuPreviewType

✳️ Default: DEFAULT
TBA
🔤 previewSize

⚛️ MenuPreviewSize

✳️ Default: INHERIT
TBA
🔤 isResizeAnimated

⚛️ boolean

✳️ Default: true
TBA
🔤 borderRadius

⚛️ number
TBA
🔤 backgroundColor

⚛️ DynamicColor ¦ string
📌 DynamicColor
TBA
🔤 previewSize

⚛️ ContextMenuInteractionCommitStyle

✳️ Default: dismiss
TBA
🔤 targetViewNode

⚛️ number
TBA

String Union: ContextMenuInteractionCommitStyle
Name and Type Description
⚛️ dismiss TBA
⚛️ pop TBA

String Union: MenuPreviewSize
Name and Type Description
⚛️ INHERIT TBA
⚛️ STRETCH TBA

String Union: MenuPreviewType
Name and Type Description
⚛️ DEFAULT TBA
⚛️ CUSTOM TBA

📄 MenuAuxiliaryPreviewConfig.ts


Object Type: MenuAuxiliaryPreviewConfig
Name and Type Description
🔤 height

⚛️ number
TBA
🔤 anchorPosition

⚛️ MenuAuxiliaryPreviewAnchorPosition

✳️ Default: automatic
TBA
🔤 alignmentHorizontal

⚛️ MenuAuxiliaryPreviewHorizontalAlignment

✳️ Default: stretchPreview
TBA
🔤 marginPreview

⚛️ number
TBA
🔤 marginAuxiliaryPreview

⚛️ number
TBA
🔤 transitionConfigEntrance

⚛️ MenuAuxiliaryPreviewTransitionConfig
TBA
🔤 transitionEntranceDelay

⚛️ MenuAuxiliaryPreviewTransitionEntranceDelay
TBA

String Union Type: MenuAuxiliaryPreviewAnchorPosition
Name and Type Description
⚛️ top TBA
⚛️ bottom TBA
⚛️ automatic TBA

String Union Type: MenuAuxiliaryPreviewHorizontalAlignment
Name and Type Description
⚛️ stretchScreen TBA
⚛️ stretchPreview TBA
⚛️ previewLeading TBA
⚛️ previewTrailing TBA
⚛️ previewCenter TBA

String Union Type: UIViewAnimateOptions
Name and Type Description
⚛️ curveEaseIn TBA
⚛️ curveEaseOut TBA
⚛️ curveEaseInOut TBA
⚛️ curveLinear TBA

Object Type: UIViewAnimateConfig
Name and Type Description
🔤 duration

⚛️ number
TBA
🔤 delay

⚛️ number
TBA
🔤 options

⚛️ UIViewAnimateOptions[]
TBA

Object Union Type: MenuAuxiliaryPreviewTransitionConfig

This type is extends/union-ed with UIViewAnimateConfig object type, and such is not listed in this section. Please see UIViewAnimateConfig type for the other object properties.

This type is an object tagged union type, with the transition property being the tag that separates the unions. The table below defines the possible valid values that can be assigned to the type property (the subsequent tables are the different possible unions).

Name and Type Description
🔤 transition

⚛️ string i.e. 'none' ¦ 'fade'
'slide' ¦ 'zoom' ¦ 'zoomAndSlide'
TBA

Name and Type Description
🔤 transition

⚛️ string i.e. none
TBA

Name and Type Description
🔤 transition

⚛️ string i.e. fade
TBA

Name and Type Description
🔤 transition

⚛️ string i.e. slide
TBA

Name and Type Description
🔤 transition

⚛️ string i.e. zoom
TBA

Name and Type Description
🔤 transition

⚛️ string i.e. zoomAndSlide
TBA

Mixed Union Type: MenuAuxiliaryPreviewTransitionEntranceDelay.
Name and Type Description
⚛️ number TBA
⚛️ RECOMMENDED TBA
⚛️ AFTER_PREVIEW TBA

📄 MenuIconConfig.ts


Object Type: IconConfig

This has been deprecated and will be removed in a future version. Use ImageItemConfig instead. For documentation regarding IconConfig, please see the documentation in the old README.


📄 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

Object: LIB_ENV

TBA


Type Description
🔤 isContextMenuButtonSupported

⚛️ boolean
TBA
🔤 isContextMenuViewSupported

⚛️ boolean
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.menuConfig prop accepts an optional MenuConfig object. The object will then be used to create and configure the context menu

    • You can set the context menu title via passing a string value to the MenuConfig.menuTitle property.

    • To populate the context menu with items, you can pass a MenuActionConfig object to the MenuConfig.menuItems property.

  • A MenuActionConfig object represents an action item in the context menu (e.g. copy, paste, delete, etc).

    • The MenuActionConfig.actionKey property serves as a unique identifier for your menu action.

  • You will receive the value you passed in MenuActionConfig.actionKey in the ContextMenuView.onPressMenuItem event (i.e. via the nativeEvent object).

    • In other words, the actionKey allows you to identify which menu action item was selected/pressed.

    • 📝 Note: Make sure that the actionKey is unique for each instance of the ContextMenuView component.

  • You can use the ContextMenuView.onPressMenuItem event prop to get notified whenever a menu action item has been selected.

    • The function you pass to the onPressMenuItem prop receives a OnPressMenuItemEventObject object.

    • Details about the selected menu action item can be accessed via the OnPressMenuItemEventObject.nativeEvent object.

    • E.g. OnPressMenuItemEventObject.nativeEvent.actionKey.

  • 📝 Note: If shouldWaitForMenuToHide
    BeforeFiringOnPressMenuItem prop is set to true (which it is by default), then this event will fire after onMenuDidHide is triggered.

🔗 Full Example

// 📝 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={{
        // Note: If you don't want a menu title to appear for your 
        // context menu, you can just pass in an empty string
        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>
  );
};

screenshot

Gif


ContextMenuView Example 02

A basic context menu that has 3 menu action items, each with a different "SF Symbols" icon. This examples shows how to add a system icon in the context menu action.


  • A MenuActionConfig object can be configured to show an icon via the MenuActionConfig.icon property.

    • The icon property accepts a ImageItemConfig object.

    • A ImageItemConfig object is used to describe images/assets (e.g. SF Symbols icons, images, xcasset images, programmatic images, etc).

  • In this example, we want to use a "SF Symbols" icon for the menu action.

    • In order to do this, the ImageItemConfig.type property must be set to "IMAGE_SYSTEM".

    • Passing in a value of "IMAGE_SYSTEM" to the type property means that we want to create a "SF Symbols" system icon.

    • Using a "SF Symbols" icon requires iOS 13+.


  • In order to configure what kind of "SF Symbols" icon we want to use for the menu action, we need to pass in a ImageSystemConfig object to the ImageItemConfig.imageValue property.

    • We set what kind of icon to use via passing a string value to the ImageSystemConfig.systemName property.

    • The string value passed to the systemName property 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.

🔗 Full Example

// 📝 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>
  );
};

screenshot

Gif


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 separate list of menu actions.

    • Tapping/selecting a submenu will show another context menu,

  • The MenuConfig.menuItems property can accept a MenuActionConfig object, or a MenuConfig object.

    • Passing in a MenuActionConfig object to MenuConfig.menuItems makes a menu action, conversely passing in a MenuConfig object will create a submenu item.

    • In other words, to make a submenu, you just need to pass a MenuConfig item in the MenuConfig.menuItems property.

      • 📝 Note: You can nest as many submenu's you want (but just remember that having more than 3 nested submenus is considered bad UX).

🔗 Full Example

 // 📝 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>
  );
};

screenshot

Gif


ContextMenuView Example 04

This example context menu showcases the MenuActionConfig.menuAttributes property.


  • The MenuActionConfig.menuAttributes property accepts an array of string (i.e. an array of MenuAttributes items).

  • In this example, the context menu has 3 actions, each with a different menu attribute assigned to it.

    • The first menu action is a "disabled" action. It has it's menuAttributes set to [disabled].

    • The action title text and icon becomes grey out.

  • The second menu action is a destructive action. It has it's menuAttributes set to [destructive].

    • The action title text and icon becomes red.

  • The third menu action is a "hidden" action. It has it's menuAttributes set 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 disabled action.

🔗 Full Example

 // 📝 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>
  );
};

screenshot

Gif


ContextMenuView Example 05

🔗 Full Example

 // 📝 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>
  );
};

screenshot

Gif


ContextMenuView Example 06

🔗 Full Example

 // 📝 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>
  );
};

screenshot

Gif


ContextMenuView Example 07

🔗 Full Example

 // 📝 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>
  );
};

screenshot

Gif


ContextMenuView Example 08

🔗 Full Example

 // 📝 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>
  );
};

screenshot

Gif


ContextMenuView Example 09

🔗 Full Example

 // 📝 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>
  );
};

screenshot

Gif


ContextMenuView Example 10

🔗 Full Example

 // 📝 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>
  );
};

screenshot

Gif


ContextMenuView Example 11

🔗 Full Example

 // 📝 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>
  );
};

screenshot

Gif


ContextMenuView Example 12

🔗 Full Example

 // 📝 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>
  );
};

screenshot

Gif


ContextMenuView Example 13

🔗 Full Example

 // 📝 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>
  );
};

screenshot

Gif


ContextMenuView Example 14

🔗 Full Example

 // 📝 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>
  );
};

screenshot

Gif


ContextMenuView Example 15

🔗 Full Example

 // 📝 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,
  }
});

screenshot

Gif


ContextMenuView Example 16

🔗 Full Example

 // 📝 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>
  );
};

screenshot

Gif


ContextMenuView Example 17

🔗 Full Example

 // 📝 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>
  );
};

screenshot

Gif


ContextMenuView Example 18

🔗 Full Example

 // 📝 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>
  );
};

screenshot

Gif


ContextMenuButton Example 01

🔗 Full Example

 // 📝 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>
  );
};

screenshot

Gif


ContextMenuButton Example 02

🔗 Full Example

 // 📝 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>
  );
};

screenshot

Gif



F. Showcase, Tests and Demos



G. Meta



H. Licence

MIT