@shaquillehinds/react-native-in-app-notification
v0.1.0
Published
A simple in app notification for react native that just works.
Downloads
511
Maintainers
Readme
@shaquillehinds/react-native-in-app-notification
A beautiful, customizable, and performant in-app notification system for React Native that just works. Built with React Native Reanimated for smooth 60fps animations and gesture support.
✨ Features
- 🎨 Fully Customizable - Complete control over styling, sizing, and behavior
- 📱 Cross-Platform - Works seamlessly on iOS and Android
- 🎭 Flexible Content - Support for both data-driven notifications and custom components
- 🖼️ Image Support - Automatic detection and optimization for expo-image, react-native-fast-image, or standard Image
- ⚡ Performant - Built on Reanimated for smooth 60fps animations
- 👆 Gesture Support - Swipe up to dismiss notifications
- 📐 Responsive - Automatic orientation and screen size handling
- 🎯 TypeScript - Full TypeScript support with comprehensive type definitions
- 🎪 Queue Management - Smart notification stacking and timing
- 🔔 Lifecycle Hooks - onEnter, onLeave, and onPress callbacks
📦 Installation
npm install @shaquillehinds/react-native-in-app-notificationor
yarn add @shaquillehinds/react-native-in-app-notificationPeer Dependencies
This package requires the following peer dependencies:
npm install react-native-reanimated react-native-gesture-handleror
yarn add react-native-reanimated react-native-gesture-handlerNote: This package depends on @shaquillehinds/react-native-essentials which will be installed automatically.
Additional Configuration
For React Native Reanimated, add the Babel plugin to your babel.config.js:
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: ['react-native-reanimated/plugin'],
};For React Native Gesture Handler, wrap your app with GestureHandlerRootView:
import { GestureHandlerRootView } from 'react-native-gesture-handler';
export default function App() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
{/* Your app code */}
</GestureHandlerRootView>
);
}🚀 Quick Start
1. Wrap Your App with the Provider
import { InAppNotificationProvider } from '@shaquillehinds/react-native-in-app-notification';
export default function App() {
return (
<InAppNotificationProvider>
{/* Your app code */}
</InAppNotificationProvider>
);
}2. Use the Hook to Show Notifications
import { useInAppNotification } from '@shaquillehinds/react-native-in-app-notification';
function MyComponent() {
const { addNotification } = useInAppNotification();
const showNotification = () => {
addNotification({
content: {
type: 'data',
payload: {
title: 'Success!',
message: 'Your action was completed successfully.',
},
},
duration: 3000,
});
};
return (
<Button title="Show Notification" onPress={showNotification} />
);
}📖 API Reference
InAppNotificationProvider
The provider component that manages notification state and renders notifications.
Props
| Prop | Type | Default | Description |
| ------------------- | ---------------------- | ----------- | --------------------------------------------------- |
| notificationStyle | StyleProp<ViewStyle> | undefined | Global style applied to all notifications |
| avoidStatusBar | boolean | undefined | Whether to avoid the status bar area (Android only) |
| width | number | 85 | Default notification width (percentage) |
| height | number | undefined | Default notification height (percentage) |
| titleWidth | number | 70 | Default title width (percentage) |
| messageWidth | number | 70 | Default message width (percentage) |
| contentWidth | number | undefined | Default content container width (percentage) |
| imageSize | number | 12 | Default image size (percentage) |
| borderRadius | number | 5 | Default border radius (percentage) |
Example
<InAppNotificationProvider
avoidStatusBar={true}
width={90}
borderRadius={8}
notificationStyle={{
backgroundColor: '#1a1a1a',
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
}}
>
{children}
</InAppNotificationProvider>useInAppNotification Hook
Returns methods to control notifications.
Return Value
{
addNotification: (notificationItem: Omit<NotificationItem, 'id'>, id?: string) => void;
updateNotification: (notificationId: string, notificationItem: Omit<NotificationItem, 'id'>) => void;
removeNotification: (notificationId: string) => void;
}Methods
addNotification(notificationItem, id?)
Adds a new notification to the queue.
notificationItem: The notification configuration (without id)id(optional): Custom notification ID for tracking
updateNotification(notificationId, notificationItem)
Updates an existing notification.
notificationId: The ID of the notification to updatenotificationItem: The new notification configuration
removeNotification(notificationId)
Removes a notification from the queue.
notificationId: The ID of the notification to remove
NotificationItem Type
The core notification configuration object.
type NotificationItem = {
id: string; // Auto-generated if not provided
style?: StyleProp<ViewStyle>; // Individual notification style
content: NotificationContent; // Notification content
duration?: number; // Display duration in milliseconds (default: 5000)
activeOpacity?: number; // Touch opacity (default: 0.8)
onPress?: (content: NotificationContent, dismiss: () => void) => void;
onNotificationLeave?: () => void;
onNotificationEnter?: () => void;
};NotificationContent Type
Defines the notification content, which can be either data-driven or a custom component.
Data Type Notification
{
type: 'data';
payload: {
title?: string;
message?: string;
Icon?: JSX.Element;
image?: ImageSourcePropType;
imageStyle?: StyleProp<ImageStyle>;
titleStyle?: StyleProp<TextStyle>;
messageStyle?: StyleProp<TextStyle>;
contentContainerStyle?: StyleProp<ViewStyle>;
// Size overrides
width?: number;
height?: number;
titleWidth?: number;
messageWidth?: number;
contentWidth?: number;
imageSize?: number;
borderRadius?: number;
};
}Component Type Notification
{
type: 'component';
payload: React.ReactNode;
}💡 Usage Examples
Basic Text Notification
const { addNotification } = useInAppNotification();
addNotification({
content: {
type: 'data',
payload: {
title: 'New Message',
message: 'You have received a new message from John.',
},
},
duration: 4000,
});Notification with Image
addNotification({
content: {
type: 'data',
payload: {
title: 'Profile Updated',
message: 'Your profile picture has been changed.',
image: require('./assets/avatar.png'),
imageStyle: {
borderRadius: 25,
},
},
},
});Notification with Custom Icon
import { Icon } from 'your-icon-library';
addNotification({
content: {
type: 'data',
payload: {
title: 'Success!',
message: 'Operation completed successfully.',
Icon: <Icon name="check-circle" size={40} color="#4CAF50" />,
},
},
});Custom Styled Notification
addNotification({
content: {
type: 'data',
payload: {
title: 'Error',
message: 'Something went wrong. Please try again.',
titleStyle: {
color: '#F44336',
fontWeight: 'bold',
fontSize: 16,
},
messageStyle: {
color: '#666',
fontSize: 14,
},
contentContainerStyle: {
backgroundColor: '#FFEBEE',
padding: 16,
},
},
},
style: {
borderLeftWidth: 4,
borderLeftColor: '#F44336',
},
duration: 5000,
});Interactive Notification
addNotification({
content: {
type: 'data',
payload: {
title: 'New Friend Request',
message: 'John Doe wants to connect with you.',
image: { uri: 'https://example.com/avatar.jpg' },
},
},
onPress: (content, dismiss) => {
// Navigate to friend request screen
navigation.navigate('FriendRequests');
dismiss(); // Dismiss the notification
},
activeOpacity: 0.7,
});Custom Component Notification
const CustomNotification = () => (
<View style={{ padding: 20, backgroundColor: '#2196F3', borderRadius: 10 }}>
<Text style={{ color: 'white', fontSize: 18, fontWeight: 'bold' }}>
Custom Design
</Text>
<Text style={{ color: 'white', fontSize: 14 }}>
You have full control over the UI!
</Text>
</View>
);
addNotification({
content: {
type: 'component',
payload: <CustomNotification />,
},
duration: 3000,
});Notification with Lifecycle Callbacks
addNotification({
content: {
type: 'data',
payload: {
title: 'Download Complete',
message: 'Your file has been downloaded successfully.',
},
},
onNotificationEnter: () => {
console.log('Notification appeared');
// Play sound, haptic feedback, etc.
},
onNotificationLeave: () => {
console.log('Notification dismissed');
// Cleanup, analytics, etc.
},
});Updating a Notification
const { addNotification, updateNotification } = useInAppNotification();
// Add with custom ID
const notificationId = 'download-progress';
addNotification(
{
content: {
type: 'data',
payload: {
title: 'Downloading...',
message: '0% complete',
},
},
duration: 10000,
},
notificationId
);
// Later, update the progress
updateNotification(notificationId, {
content: {
type: 'data',
payload: {
title: 'Downloading...',
message: '50% complete',
},
},
duration: 10000,
});Notification Queue Example
// Notifications will automatically stack and animate nicely
const showMultiple = () => {
addNotification({
content: {
type: 'data',
payload: { title: 'First', message: 'First notification' },
},
});
addNotification({
content: {
type: 'data',
payload: { title: 'Second', message: 'Second notification' },
},
});
addNotification({
content: {
type: 'data',
payload: { title: 'Third', message: 'Third notification' },
},
});
};🎨 Styling Guide
Global Styling
Use the provider props to set default styles for all notifications:
<InAppNotificationProvider
width={88}
borderRadius={12}
notificationStyle={{
backgroundColor: '#ffffff',
shadowColor: '#000',
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.3,
shadowRadius: 4.65,
elevation: 8,
}}
>Per-Notification Styling
Override global styles for individual notifications:
addNotification({
content: {
type: 'data',
payload: {
title: 'Special Notification',
message: 'This one looks different!',
titleStyle: { color: '#9C27B0' },
messageStyle: { color: '#555' },
contentContainerStyle: {
backgroundColor: '#F3E5F5',
},
},
},
style: {
width: '95%',
borderRadius: 15,
},
});Theme System Example
// Define your notification themes
const notificationThemes = {
success: {
style: {
borderLeftWidth: 4,
borderLeftColor: '#4CAF50',
},
payload: {
titleStyle: { color: '#2E7D32' },
contentContainerStyle: { backgroundColor: '#E8F5E9' },
},
},
error: {
style: {
borderLeftWidth: 4,
borderLeftColor: '#F44336',
},
payload: {
titleStyle: { color: '#C62828' },
contentContainerStyle: { backgroundColor: '#FFEBEE' },
},
},
info: {
style: {
borderLeftWidth: 4,
borderLeftColor: '#2196F3',
},
payload: {
titleStyle: { color: '#1565C0' },
contentContainerStyle: { backgroundColor: '#E3F2FD' },
},
},
};
// Use the themes
const showSuccess = (title: string, message: string) => {
addNotification({
content: {
type: 'data',
payload: {
title,
message,
...notificationThemes.success.payload,
},
},
style: notificationThemes.success.style,
});
};🔧 Advanced Configuration
Responsive Sizing
All size values are percentages relative to screen dimensions:
<InAppNotificationProvider
width={85} // 85% of screen width
height={10} // 10% of screen height
imageSize={15} // 15% of screen width
titleWidth={70} // 70% of notification width
messageWidth={70} // 70% of notification width
borderRadius={6} // 6% of shortest screen dimension
/>Image Handling
The package automatically detects and uses the best image component available:
expo-image(preferred)react-native-fast-image- Standard
Image(fallback)
No additional configuration needed!
Android Status Bar
On Android, you can control whether notifications avoid the status bar:
<InAppNotificationProvider avoidStatusBar={true}>Performance Optimization
For best performance:
- Memoize custom components used in notifications
- Use callback refs for lifecycle hooks
- Limit the number of simultaneous notifications (3-5 recommended)
- Use appropriate durations (3000-5000ms for most cases)
🐛 Troubleshooting
Notifications Not Showing
- Ensure
InAppNotificationProviderwraps your component tree - Verify
GestureHandlerRootViewwraps your app - Check that Reanimated is properly configured
Animation Issues
- Make sure Reanimated Babel plugin is last in your plugins array
- Clear Metro cache:
npx react-native start --reset-cache - Rebuild your app after adding the Babel plugin
TypeScript Errors
Ensure you have the correct peer dependency versions installed:
npm install --save-dev @types/react @types/react-nativeCustom Components Not Rendering
When using type: 'component', ensure your component:
- Is wrapped in a View with proper dimensions
- Handles its own styling completely
- Doesn't rely on parent context that might not be available
📝 TypeScript Support
Full TypeScript definitions are included. Import types as needed:
import type {
NotificationItem,
NotificationContent,
NotificationDataPayload,
NotificationSizeOptions,
InAppNotificationProviderProps,
} from '@shaquillehinds/react-native-in-app-notification';🤝 Contributing
Contributions are welcome! Please read our Contributing Guide and Code of Conduct.
📄 License
MIT © Shaquille Hinds
🔗 Links
🙏 Dependencies
This package is built on top of excellent open-source projects:
Made with ❤️ by Shaquille Hinds
