suiss/uim · React Native Component

Context Menu

A menu that opens at the touch point when an area is long-pressed.

Context Menu is an open-source mobile component from suiss/uim for React Native and Expo, with SwiftUI and Jetpack Compose versions built from the same design tokens. The @esuiss/uim CLI copies its source into your project, so you own the code.

iOS
Context Menu (open by default) on iOS in light mode

ContextMenu attaches a menu to a ContextMenuTrigger area. A long press opens ContextMenuContent at the position of the finger with a medium impact haptic. The content renders through a portal (inside a full-window overlay on iOS) as a raised, rounded card.

Items can be plain actions, checkbox items, radio items in a group, or a submenu. ContextMenuSubContent expands in place under its trigger, and the caret turns to point down while it is open.

Installation

$ pnpm dlx @esuiss/uim@latest add context-menu

The CLI also adds what it builds on: Icon, Text.

Manual

  1. Install the dependencies:
npx expo install cn phosphor-react-native react-native-reanimated react-native-screens react-native-svg react-native-worklets
  1. Add the pieces it builds on: Icon, Text, and the primitives components/primitives/context-menu.tsx, components/primitives/use-render.tsx.

  2. Copy the source into components/ui/context-menu.tsx:

uniwind/components/ui/context-menu.tsx
import { cn } from "cn"
import { CaretRightIcon, CheckIcon } from "phosphor-react-native"
import * as React from "react"
import { Platform, View } from "react-native"
import { FadeIn, ReduceMotion } from "react-native-reanimated"
import { FullWindowOverlay as RNFullWindowOverlay } from "react-native-screens"
import * as ContextMenuPrimitive from "@/components/primitives/context-menu"
import { resolveClassName } from "@/components/primitives/use-render"
import { AnimatedView } from "@/components/ui/animated-view"
import { Icon } from "@/components/ui/icon"
import { TextClassContext } from "@/components/ui/text"

const ContextMenu = ContextMenuPrimitive.Root

const ContextMenuTrigger = ContextMenuPrimitive.Trigger
  1. Update the import paths to match your project.

Usage

import { ContextMenuContent, ContextMenuSubTrigger, ContextMenuSubContent, ContextMenuItem, ContextMenuCheckboxItem, ContextMenuRadioItem, ContextMenuLabel, ContextMenuSeparator } from "@/components/ui/context-menu"
<ContextMenuDemo defaultOpen />

Wrap the long-pressable area in ContextMenuTrigger and list ContextMenuItems in ContextMenuContent. Items close the menu when pressed unless closeOnPress={false}.

Use ContextMenuCheckboxItem with checked and onCheckedChange, and ContextMenuRadioItem inside a ContextMenuRadioGroup with value and onValueChange. Group items with ContextMenuGroup and ContextMenuLabel, and divide sections with ContextMenuSeparator.

Set variant="destructive" on an item that deletes or removes. Use inset on items without an icon to align them with items that have one.

Examples

Default

iOS
Context Menu on iOS in light mode

Simple

A short list of plain items.

iOS
Context Menu (simple) on iOS in light mode

API Reference

ContextMenuContent

Floating menu card.

ExtendsReact.ComponentProps<typeof ContextMenuPrimitive.Popup>PositionerProps
PropType
About
Name of the portal host to render into.
Type
string
Default
—

ContextMenuSubTrigger

Row that expands the submenu.

ExtendsReact.ComponentProps<typeof ContextMenuPrimitive.SubmenuTrigger>
PropType
Type
React.ReactNode
Default
—
About
Extra classes for the caret icon.
Type
string
Default
—
About
Adds start padding.
Type
boolean
Default
—

ContextMenuSubContent

Items of the submenu.

ExtendsReact.ComponentProps<typeof ContextMenuPrimitive.Popup>

ContextMenuItem

Action row.

ExtendsReact.ComponentProps<typeof ContextMenuPrimitive.Item>
PropType
About
Adds start padding to align with icon items.
Type
boolean
Default
—
About
default or destructive.
Type
"default""destructive"
Default
"default"

ContextMenuCheckboxItem

Row with a check mark that toggles.

ExtendsReact.ComponentProps<typeof ContextMenuPrimitive.CheckboxItem>
PropType
Type
React.ReactNode
Default
—
About
Adds start padding.
Type
boolean
Default
—

ContextMenuRadioItem

Row that selects one value in its group.

ExtendsReact.ComponentProps<typeof ContextMenuPrimitive.RadioItem>
PropType
Type
React.ReactNode
Default
—
About
Adds start padding.
Type
boolean
Default
—

ContextMenuLabel

Heading for a group.

ExtendsReact.ComponentProps<typeof ContextMenuPrimitive.GroupLabel>
PropType
About
Adds start padding.
Type
boolean
Default
—

ContextMenuSeparator

Line between sections.

ExtendsReact.ComponentProps<typeof ContextMenuPrimitive.Separator>

Accessibility

  • The trigger exposes a longpress accessibility action, so VoiceOver and TalkBack users can open the menu, and reports its expanded state.
  • The popup has the menu role; items use menuitem, checkbox and radio roles, and radio groups use radiogroup.
  • Separators have the separator role.

Notes

  • Uses bg-surface-raised, bg-item-pressed and bg-danger-surface-pressed tokens; light and dark follow the system appearance.
  • The fade-in respects the system Reduce Motion setting.