Back to Components

Blur Menu

Menu
8 months ago

About

BlurMenu Component

A beautifully animated, blur-background menu component for React Native with Expo. Features smooth spring animations, customizable positioning, and a sophisticated modal management system.

Features

  • Smooth Animations: Spring-based animations with staggered menu item entrances
  • 🎯 Flexible Positioning: Support for 9 different FAB positions (top, bottom, center, left, right combinations)
  • 🌊 Blur Background: Elegant blur effect using Expo's BlurView
  • 🎭 Modal Management: Global modal manager ensures only one menu is active at a time
  • 🎨 Customizable: Support for custom icons, titles, and styling
  • 📱 Safe Area Aware: Automatically handles device safe areas
  • 🎪 Custom Triggers: Use your own component as the menu trigger

Dependencies

This component requires the following packages:

bash
npm install expo-blur react-native-reanimated react-native-safe-area-context @expo/vector-icons

Basic Usage

tsx
import BlurMenu, { MenuItem } from '@/components/BlurMenu'; import { useState } from 'react'; const menuItems: MenuItem[] = [ { id: 'profile', icon: 'person-outline', title: 'Profile', onPress: () => console.log('Profile pressed') }, { id: 'settings', icon: 'settings-outline', title: 'Settings', onPress: () => console.log('Settings pressed') }, { id: 'logout', icon: 'log-out-outline', title: 'Logout', onPress: () => console.log('Logout pressed') } ]; export default function MyScreen() { const [menuVisible, setMenuVisible] = useState(false); return ( <BlurMenu visible={menuVisible} onToggle={() => setMenuVisible(!menuVisible)} menuItems={menuItems} title="Main Menu" fabPosition="bottom-right" /> ); }

Props

PropTypeDefaultDescription
visibleboolean-Required. Controls menu visibility
onToggle() => void-Required. Callback when menu should toggle
menuItemsMenuItem[]-Required. Array of menu items
positionMenuPosition'center'Menu content alignment ('left' | 'right' | 'center')
titlestring'Menu'Menu title displayed at the top
fabPositionFabPosition'bottom-center'FAB trigger position
childrenReact.ReactNode-Custom trigger component (replaces default FAB)
classNamestring-Additional CSS class for custom trigger

MenuItem Interface

tsx
interface MenuItem { id?: string; // Optional unique identifier icon?: React.ComponentType<any> // Icon component, React node, or Ionicons name | React.ReactNode | string; title: string; // Menu item label onPress?: () => void; // Callback when item is pressed }

Position Types

tsx
type MenuPosition = 'left' | 'right' | 'center'; type FabPosition = | 'top-left' | 'top-right' | 'top-center' | 'bottom-left' | 'bottom-right' | 'bottom-center' | 'left' | 'right' | 'center';

Advanced Usage Examples

Custom Trigger Component

tsx
<BlurMenu visible={menuVisible} onToggle={() => setMenuVisible(!menuVisible)} menuItems={menuItems} title="Actions" > <View style={styles.customTrigger}> <Ionicons name="ellipsis-horizontal" size={24} color="white" /> </View> </BlurMenu>

Different FAB Positions

tsx
// Top-right corner menu <BlurMenu visible={menuVisible} onToggle={() => setMenuVisible(!menuVisible)} menuItems={menuItems} fabPosition="top-right" title="Quick Actions" /> // Left-side menu <BlurMenu visible={menuVisible} onToggle={() => setMenuVisible(!menuVisible)} menuItems={menuItems} fabPosition="left" position="left" title="Navigation" />

Custom Icons

tsx
const menuItems: MenuItem[] = [ { icon: <MyCustomIcon size={20} color="white" />, title: 'Custom Action', onPress: () => handleCustomAction() }, { icon: () => <AnotherIcon />, title: 'Function Icon', onPress: () => handleAnotherAction() } ];

Menu with Context Actions

tsx
const contextMenuItems: MenuItem[] = [ { icon: 'copy-outline', title: 'Copy', onPress: () => handleCopy() }, { icon: 'share-outline', title: 'Share', onPress: () => handleShare() }, { icon: 'trash-outline', title: 'Delete', onPress: () => handleDelete() } ]; // Triggered by long press on an item <BlurMenu visible={contextMenuVisible} onToggle={() => setContextMenuVisible(!contextMenuVisible)} menuItems={contextMenuItems} title="Actions" fabPosition="center" />

Animation Details

The component features sophisticated animations:

  • Spring Animations: Uses react-native-reanimated with optimized spring configurations
  • Staggered Entrance: Menu items appear with a 50ms delay between each item
  • Direction-Aware: Animation direction depends on FAB position
  • Smooth Transitions: 200-300ms timing for opacity and blur effects

Modal Management

The component includes a global modal manager that:

  • Ensures only one BlurMenu is active at a time
  • Automatically closes other menus when a new one opens
  • Handles proper cleanup when components unmount
  • Prevents modal conflicts in complex navigation scenarios

Styling Notes

  • Menu uses a dark blur background with white text
  • Menu items have subtle bottom borders with transparency
  • FAB has a subtle shadow for depth
  • All animations respect device safe areas
  • Responsive design adapts to different screen sizes

Best Practices

  1. Menu Items: Keep menu items concise (5-7 items maximum)
  2. Icons: Use consistent icon styling across menu items
  3. Position: Choose FAB position based on your app's navigation patterns
  4. Performance: Menu items are optimized with proper key props
  5. Accessibility: Consider adding accessibility labels for better UX

Troubleshooting

Menu not appearing: Ensure expo-blur is properly installed and linked.

Animations stuttering: Check that react-native-reanimated is configured correctly in your project.

Multiple menus conflict: The modal manager should handle this automatically, but ensure each BlurMenu has unique menu items.

License

This component is part of the landing-rn-components library.

Posted by

E

eren

@eren