Reference version

This is documentation for the next SDK version. For up-to-date documentation, see the latest version (SDK 54).

ContextMenu

A SwiftUI ContextMenu component for displaying context menus.

iOS
tvOS

Expo UI ContextMenu matches the official SwiftUI contextMenu API and displays a menu when long-pressed.

Installation

Terminal
- npx expo install @expo/ui

If you are installing this in an existing React Native app, make sure to install expo in your project.

Usage

Basic context menu

BasicContextMenuExample.tsx
import { Host, ContextMenu, Button, Text } from '@expo/ui/swift-ui'; export default function BasicContextMenuExample() { return ( <Host matchContents> <ContextMenu> <ContextMenu.Items> <Button label="Edit" onPress={() => console.log('Edit')} /> <Button label="Delete" role="destructive" onPress={() => console.log('Delete')} /> </ContextMenu.Items> <ContextMenu.Trigger> <Text>Long press me</Text> </ContextMenu.Trigger> </ContextMenu> </Host> ); }

Context menu with system images

ContextMenuWithImagesExample.tsx
import { Host, ContextMenu, Button, Text } from '@expo/ui/swift-ui'; export default function ContextMenuWithImagesExample() { return ( <Host matchContents> <ContextMenu> <ContextMenu.Items> <Button label="Share" systemImage="square.and.arrow.up" onPress={() => console.log('Share')} /> <Button label="Favorite" systemImage="heart" onPress={() => console.log('Favorite')} /> <Button label="Delete" systemImage="trash" role="destructive" onPress={() => console.log('Delete')} /> </ContextMenu.Items> <ContextMenu.Trigger> <Text>Long press me</Text> </ContextMenu.Trigger> </ContextMenu> </Host> ); }

Context menu with preview

Use ContextMenu.Preview to show a custom preview above the menu when opened.

ContextMenuWithPreviewExample.tsx
import { View, Text as RNText } from 'react-native'; import { Host, ContextMenu, Button, Text } from '@expo/ui/swift-ui'; export default function ContextMenuWithPreviewExample() { return ( <Host matchContents> <ContextMenu> <ContextMenu.Items> <Button label="Edit" onPress={() => console.log('Edit')} /> <Button label="Delete" role="destructive" onPress={() => console.log('Delete')} /> </ContextMenu.Items> <ContextMenu.Trigger> <Text>Long press me</Text> </ContextMenu.Trigger> <ContextMenu.Preview> <View style={{ width: 200, height: 100, backgroundColor: '#f0f0f0', padding: 16 }}> <RNText>Preview Content</RNText> </View> </ContextMenu.Preview> </ContextMenu> </Host> ); }

Context menu with picker

ContextMenuWithPickerExample.tsx
import { useState } from 'react'; import { Host, ContextMenu, Button, Text, Picker } from '@expo/ui/swift-ui'; import { pickerStyle, tag } from '@expo/ui/swift-ui/modifiers'; export default function ContextMenuWithPickerExample() { const [selectedIndex, setSelectedIndex] = useState<number | undefined>(0); return ( <Host matchContents> <ContextMenu> <ContextMenu.Items> <Button label="Action" onPress={() => console.log('Action')} /> <Picker label="Size" modifiers={[pickerStyle('menu')]} selection={selectedIndex} onSelectionChange={setSelectedIndex}> {['Small', 'Medium', 'Large'].map((option, index) => ( <Text key={index} modifiers={[tag(index)]}> {option} </Text> ))} </Picker> </ContextMenu.Items> <ContextMenu.Trigger> <Text>Long press me</Text> </ContextMenu.Trigger> </ContextMenu> </Host> ); }

Context menu with sections

Use Section and Divider components to organize menu items.

ContextMenuWithSectionsExample.tsx
import { Host, ContextMenu, Button, Text, Section, Divider } from '@expo/ui/swift-ui'; export default function ContextMenuWithSectionsExample() { return ( <Host matchContents> <ContextMenu> <ContextMenu.Items> <Section title="Actions"> <Button label="Edit" onPress={() => console.log('Edit')} /> <Button label="Duplicate" onPress={() => console.log('Duplicate')} /> </Section> <Divider /> <Button label="Delete" role="destructive" onPress={() => console.log('Delete')} /> </ContextMenu.Items> <ContextMenu.Trigger> <Text>Long press me</Text> </ContextMenu.Trigger> </ContextMenu> </Host> ); }

Nested context menus

Use nested ContextMenu components to create submenus.

NestedContextMenuExample.tsx
import { Host, ContextMenu, Button, Text } from '@expo/ui/swift-ui'; export default function NestedContextMenuExample() { return ( <Host matchContents> <ContextMenu> <ContextMenu.Items> <Button label="Action" onPress={() => console.log('Action')} /> <ContextMenu> <ContextMenu.Items> <Button label="Sub Action 1" onPress={() => console.log('Sub 1')} /> <Button label="Sub Action 2" onPress={() => console.log('Sub 2')} /> </ContextMenu.Items> <ContextMenu.Trigger> <Button label="More Options" /> </ContextMenu.Trigger> </ContextMenu> </ContextMenu.Items> <ContextMenu.Trigger> <Text>Long press me</Text> </ContextMenu.Trigger> </ContextMenu> </Host> ); }

API

Components

ContextMenu

iOS
tvOS

Type: React.Element<ContextMenuProps>

ContextMenu allows you to create a context menu, which can be used to provide additional options to the user.

Props of the ContextMenu component.

ContextMenuProps

children

iOS
tvOS
Type: ReactNode

The contents of the context menu. Should include ContextMenu.Trigger, ContextMenu.Items, and optionally ContextMenu.Preview.

Items

iOS
tvOS

Type: React.Element<{ children: ReactNode }>

Items visible inside the context menu. It could be Section, Divider, Button, Switch, Picker or even ContextMenu itself for nested menus. Remember to use components from the @expo/ui/swift-ui library.

Preview

iOS
tvOS

Type: React.Element<{ children: ReactNode }>

The component visible above the menu when it is opened.

Trigger

iOS
tvOS

Type: React.Element<{ children: ReactNode }>

The component visible all the time that triggers the context menu when long-pressed.