UNPKG

rn-toastify

Version:

A professional, production-ready toast notification library for React Native. Featuring smooth spring animations, swipe-to-dismiss gestures, progress bars, queue management, and a beautiful design system with light/dark themes.

164 lines (156 loc) 4.79 kB
import React from 'react'; import { View, Text, StyleSheet, Platform } from 'react-native'; import { heightPercentageToDP as hp, widthPercentageToDP as wp, } from '../utils/Pixel/Index'; import { TOAST_THEME, TOAST_COLORS } from '../utils/theme'; import ProgressBar from './ProgressBar'; /** * BaseToast — Premium shared layout for all built-in toast types. * * Design: Compact card with rounded icon badge, subtle accent, * floating shadow, and an edge-to-edge progress indicator. */ const BaseToast = ({ icon, title, message, accentColor, toastType = 'info', theme = 'light', duration, showProgress = true, children, }) => { const isDark = theme === 'dark'; const themeColors = TOAST_THEME[isDark ? 'dark' : 'light']; const colors = TOAST_COLORS[toastType] || TOAST_COLORS.info; const iconBgColor = isDark ? colors.iconBgDark : colors.iconBg; return ( <View style={[ styles.container, { backgroundColor: themeColors.background, borderColor: themeColors.border, ...Platform.select({ ios: { shadowColor: themeColors.shadow, shadowOffset: { width: 0, height: 8 }, shadowOpacity: isDark ? 0.6 : 1, shadowRadius: 24, }, android: { elevation: 8, }, }), }, ]} accessibilityRole="alert" accessibilityLiveRegion="polite" accessibilityLabel={ [title, message].filter(Boolean).join('. ') } > {/* Left Edge Accent */} <View style={[styles.leftAccent, { backgroundColor: accentColor || colors.accent }]} /> {/* Content row */} <View style={styles.body}> {/* Icon wrapper without the heavy badge background */} {icon && ( <View style={styles.iconContainer}> {icon} </View> )} {/* Text content */} <View style={styles.textContainer}> {title ? ( <Text style={[styles.title, { color: themeColors.title }]} numberOfLines={1} ellipsizeMode="tail" > {title} </Text> ) : null} {message ? ( <Text style={[ styles.message, { color: themeColors.message }, !title && styles.messageSolo, ]} numberOfLines={2} ellipsizeMode="tail" > {message} </Text> ) : null} {children} </View> </View> {/* Progress bar — flush to bottom edge */} {showProgress && duration && duration !== Infinity && ( <ProgressBar duration={duration} color={accentColor} trackColor={themeColors.progressTrack} /> )} </View> ); }; const styles = StyleSheet.create({ container: { width: wp(88), maxWidth: 400, borderRadius: 24, overflow: 'hidden', borderWidth: 1, }, leftAccent: { position: 'absolute', left: 0, top: 0, bottom: 0, width: 4, }, body: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16, paddingVertical: 14, paddingLeft: 20, }, iconContainer: { width: 36, height: 36, alignItems: 'center', justifyContent: 'center', marginRight: 12, }, textContainer: { flex: 1, justifyContent: 'center', }, title: { fontSize: 15, fontWeight: '700', letterSpacing: -0.2, lineHeight: 20, }, message: { fontSize: 13, fontWeight: '500', marginTop: 2, lineHeight: 18, letterSpacing: -0.1, }, messageSolo: { fontSize: 14, fontWeight: '600', lineHeight: 20, }, }); export default React.memo(BaseToast);