managarten/picture/docs/development/CONTEXT_MENU_EXAMPLES.md
Till-JS c712a2504a feat: integrate uload and picture, unify package naming
- Add uload project with apps/web structure
  - Reorganize from flat to monorepo structure
  - Remove PocketBase binary and local data
  - Update to pnpm and @uload/web namespace

- Add picture project to monorepo
  - Remove embedded git repository

- Unify all package names to @{project}/{app} schema:
  - @maerchenzauber/* (was @storyteller/*)
  - @manacore/* (was manacore-*, manacore)
  - @manadeck/* (was web, backend, manadeck)
  - @memoro/* (was memoro-web, landing, memoro)
  - @picture/* (already unified)
  - @uload/web

- Add convenient dev scripts for all apps:
  - pnpm dev:{project}:web
  - pnpm dev:{project}:landing
  - pnpm dev:{project}:mobile
  - pnpm dev:{project}:backend

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 04:00:36 +01:00

5.6 KiB

react-native-context-menu-view Usage Examples

Basic Context Menu

import ContextMenu from 'react-native-context-menu-view';
import { View, Text, Image } from 'react-native';

function BasicExample() {
  return (
    <ContextMenu
      actions={[
        { title: 'Save', systemIcon: 'square.and.arrow.down' },
        { title: 'Share', systemIcon: 'square.and.arrow.up' },
        { title: 'Delete', destructive: true, systemIcon: 'trash' }
      ]}
      onPress={(e) => {
        console.log('Action pressed:', e.nativeEvent.name);
        // Handle action based on e.nativeEvent.index or e.nativeEvent.name
      }}
    >
      <View className="p-4 bg-gray-100 rounded-lg">
        <Text>Long press me!</Text>
      </View>
    </ContextMenu>
  );
}

Context Menu with Submenus (iOS 14+)

import ContextMenu from 'react-native-context-menu-view';

function SubmenuExample() {
  return (
    <ContextMenu
      actions={[
        { title: 'Save', systemIcon: 'square.and.arrow.down' },
        {
          title: 'Export',
          systemIcon: 'square.and.arrow.up.on.square',
          // Nested submenu actions
          actions: [
            { title: 'Export as PDF', systemIcon: 'doc.fill' },
            { title: 'Export as Image', systemIcon: 'photo' },
            { title: 'Export as Video', systemIcon: 'video' }
          ]
        },
        { title: 'Delete', destructive: true, systemIcon: 'trash' }
      ]}
      onPress={(e) => {
        console.log('Action:', e.nativeEvent.name);
      }}
    >
      <View className="p-4 bg-blue-100 rounded-lg">
        <Text>Long press for submenu!</Text>
      </View>
    </ContextMenu>
  );
}

Context Menu with Preview

import ContextMenu from 'react-native-context-menu-view';

function PreviewExample() {
  return (
    <ContextMenu
      actions={[
        { title: 'Edit', systemIcon: 'pencil' },
        { title: 'Duplicate', systemIcon: 'plus.square.on.square' },
        { title: 'Delete', destructive: true, systemIcon: 'trash' }
      ]}
      onPress={(e) => {
        console.log('Action:', e.nativeEvent.name);
      }}
      previewBackgroundColor="white"
    >
      <Image
        source={{ uri: 'https://example.com/image.jpg' }}
        className="w-full h-48 rounded-lg"
      />
    </ContextMenu>
  );
}

Context Menu on Generated Images

import ContextMenu from 'react-native-context-menu-view';
import * as MediaLibrary from 'expo-media-library';
import * as FileSystem from 'expo-file-system';

function GeneratedImageMenu({ imageUrl }: { imageUrl: string }) {
  const handleSave = async () => {
    // Request permissions
    const { status } = await MediaLibrary.requestPermissionsAsync();
    if (status !== 'granted') {
      alert('Permission required to save images');
      return;
    }

    // Download and save image
    const fileUri = FileSystem.documentDirectory + 'generated-image.jpg';
    await FileSystem.downloadAsync(imageUrl, fileUri);
    await MediaLibrary.createAssetAsync(fileUri);
    alert('Image saved!');
  };

  return (
    <ContextMenu
      actions={[
        { title: 'Save to Photos', systemIcon: 'square.and.arrow.down' },
        { title: 'Share', systemIcon: 'square.and.arrow.up' },
        {
          title: 'More Options',
          actions: [
            { title: 'Set as Wallpaper', systemIcon: 'photo.on.rectangle' },
            { title: 'Copy', systemIcon: 'doc.on.doc' },
            { title: 'View Details', systemIcon: 'info.circle' }
          ]
        },
        { title: 'Delete', destructive: true, systemIcon: 'trash' }
      ]}
      onPress={(e) => {
        switch(e.nativeEvent.index) {
          case 0: // Save to Photos
            handleSave();
            break;
          case 1: // Share
            // Implement share
            break;
          case 2: // Delete
            // Implement delete
            break;
        }
      }}
    >
      <Image
        source={{ uri: imageUrl }}
        className="w-full h-full rounded-lg"
        resizeMode="cover"
      />
    </ContextMenu>
  );
}

Available Action Properties

interface Action {
  title: string;                    // Action title
  systemIcon?: string;              // SF Symbol name (iOS only)
  icon?: string;                    // Custom icon (Android)
  destructive?: boolean;            // Red text for destructive actions
  disabled?: boolean;               // Disable the action
  inlineChildren?: boolean;         // Show submenu items inline
  actions?: Action[];               // Nested submenu actions
}

Common SF Symbols (iOS)

  • square.and.arrow.down - Save/Download
  • square.and.arrow.up - Share/Export
  • trash - Delete
  • pencil - Edit
  • doc.on.doc - Copy
  • heart / heart.fill - Favorite
  • star / star.fill - Star/Rate
  • photo - Image
  • video - Video
  • info.circle - Info
  • eye / eye.slash - Show/Hide
  • checkmark - Confirm

Android Support

The library also works on Android with Material Design menus:

<ContextMenu
  actions={[
    { title: 'Save', icon: 'save' },  // Use Android icon names
    { title: 'Share', icon: 'share' },
    { title: 'Delete', destructive: true, icon: 'delete' }
  ]}
  onPress={(e) => {
    console.log('Action:', e.nativeEvent.index);
  }}
>
  <YourComponent />
</ContextMenu>

Tips

  1. Long Press: Context menu appears on long press by default
  2. Submenus: Nest actions arrays for submenus (iOS 14+)
  3. SF Symbols: Use Apple's SF Symbols for iOS icons
  4. Destructive Actions: Set destructive: true for delete/remove actions
  5. Event Handling: Use e.nativeEvent.index or e.nativeEvent.name to identify actions