import React, { useEffect, useRef } from "react"; import { View, Text, StyleSheet, Animated } from "react-native"; import { CheckCircle2, AlertCircle, Info } from "lucide-react-native"; interface ModalToastProps { visible: boolean; title: string; description?: string; /** * Visual style of the toast. * - success: green * - error: red * - warning: yellow * - info: blue */ variant?: "success" | "error" | "warning" | "info"; } const ModalToast: React.FC = ({ visible, title, description, variant = "error", }) => { const config = getVariantConfig(variant); const Icon = config.icon; const translateX = useRef(new Animated.Value(-40)).current; const opacity = useRef(new Animated.Value(0)).current; useEffect(() => { if (visible) { translateX.setValue(-40); opacity.setValue(0); Animated.parallel([ Animated.spring(translateX, { toValue: 0, useNativeDriver: true, speed: 20, bounciness: 6, }), Animated.timing(opacity, { toValue: 1, duration: 180, useNativeDriver: true, }), ]).start(); } }, [visible, translateX, opacity]); if (!visible) return null; return ( {title} {description ? ( {description} ) : null} ); }; function getVariantConfig(variant: "success" | "error" | "warning" | "info") { switch (variant) { case "success": return { backgroundColor: "#f1f9f5", iconBackgroundColor: "#e1f0e2", iconColor: "#16a34a", titleColor: "#000", descriptionColor: "#000", icon: CheckCircle2, borderColor: "#e1f0e2", } as const; case "warning": return { backgroundColor: "#fef7eb", iconBackgroundColor: "#ebe3d5", iconColor: "#eab308", titleColor: "#000", descriptionColor: "#000", icon: AlertCircle, borderColor: "#ebe3d5", } as const; case "info": return { backgroundColor: "#e8eefa", iconBackgroundColor: "#cdd5e2", iconColor: "#2563eb", titleColor: "#000", descriptionColor: "#000", icon: Info, borderColor: "#cdd5e2", } as const; case "error": default: return { backgroundColor: "#fbf0f1", iconBackgroundColor: "#ebd8d4", iconColor: "#dc2000", titleColor: "#000000", descriptionColor: "#000", icon: AlertCircle, borderColor: "#ebd8d4", } as const; } } const styles = StyleSheet.create({ absoluteOverlay: { zIndex: 9999, elevation: 50, }, wrapper: { alignItems: "center", paddingHorizontal: 16, marginTop: 16, }, toast: { width: "100%", maxWidth: 360, borderRadius: 12, paddingHorizontal: 16, paddingVertical: 12, flexDirection: "row", alignItems: "center", shadowColor: "#000", shadowOpacity: 0.18, shadowRadius: 8, shadowOffset: { width: 0, height: 4 }, }, iconContainer: { width: 32, height: 32, borderRadius: 16, alignItems: "center", justifyContent: "center", }, textContainer: { flex: 1, marginLeft: 12, }, title: { fontSize: 14, fontWeight: "700", }, description: { fontSize: 12, marginTop: 4, }, }); export default ModalToast;