Code Files
README.md
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:
npm install expo-blur react-native-reanimated react-native-safe-area-context @expo/vector-icons
Basic Usage
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
Prop | Type | Default | Description |
---|---|---|---|
visible | boolean | - | Required. Controls menu visibility |
onToggle | () => void | - | Required. Callback when menu should toggle |
menuItems | MenuItem[] | - | Required. Array of menu items |
position | MenuPosition | 'center' | Menu content alignment ('left' | 'right' | 'center' ) |
title | string | 'Menu' | Menu title displayed at the top |
fabPosition | FabPosition | 'bottom-center' | FAB trigger position |
children | React.ReactNode | - | Custom trigger component (replaces default FAB) |
className | string | - | Additional CSS class for custom trigger |
MenuItem Interface
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
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
<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
// 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
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
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
- Menu Items: Keep menu items concise (5-7 items maximum)
- Icons: Use consistent icon styling across menu items
- Position: Choose FAB position based on your app's navigation patterns
- Performance: Menu items are optimized with proper key props
- 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.