eletrotupi / tcc/ frontend/components/ui/Toast.tsx409c3751b50fc119fcd4ef0ef0b88531565cfd95
2.1 KB | 92 lines Raw
1
import React, { useEffect, useRef } from 'react';
2
import { Animated, StyleSheet, Text } from 'react-native';
3
import { useSafeAreaInsets } from 'react-native-safe-area-context';
4

5
export type ToastVariant = 'error' | 'success' | 'warning';
6

7
interface ToastProps {
8
  message: string;
9
  variant: ToastVariant;
10
  visible: boolean;
11
}
12

13
const VARIANT_COLORS: Record<ToastVariant, string> = {
14
  error: '#EF4444',
15
  success: '#22c55e',
16
  warning: '#F97316',
17
};
18

19
export function Toast({ message, variant, visible }: ToastProps) {
20
  const insets = useSafeAreaInsets();
21
  const translateY = useRef(new Animated.Value(-120)).current;
22
  const opacity = useRef(new Animated.Value(0)).current;
23

24
  useEffect(() => {
25
    if (visible) {
26
      Animated.parallel([
27
        Animated.spring(translateY, {
28
          toValue: 0,
29
          useNativeDriver: true,
30
          tension: 80,
31
          friction: 10,
32
        }),
33
        Animated.timing(opacity, {
34
          toValue: 1,
35
          duration: 200,
36
          useNativeDriver: true,
37
        }),
38
      ]).start();
39
    } else {
40
      Animated.parallel([
41
        Animated.timing(translateY, {
42
          toValue: -120,
43
          duration: 250,
44
          useNativeDriver: true,
45
        }),
46
        Animated.timing(opacity, {
47
          toValue: 0,
48
          duration: 200,
49
          useNativeDriver: true,
50
        }),
51
      ]).start();
52
    }
53
  }, [visible]);
54

55
  return (
56
    <Animated.View
57
      style={[
58
        styles.container,
59
        { top: insets.top + 12, backgroundColor: VARIANT_COLORS[variant] },
60
        { transform: [{ translateY }], opacity },
61
      ]}
62
      pointerEvents="none"
63
    >
64
      <Text style={styles.message} numberOfLines={3}>
65
        {message}
66
      </Text>
67
    </Animated.View>
68
  );
69
}
70

71
const styles = StyleSheet.create({
72
  container: {
73
    position: 'absolute',
74
    left: 16,
75
    right: 16,
76
    zIndex: 9999,
77
    borderRadius: 10,
78
    paddingHorizontal: 16,
79
    paddingVertical: 12,
80
    shadowColor: '#000',
81
    shadowOffset: { width: 0, height: 4 },
82
    shadowOpacity: 0.15,
83
    shadowRadius: 8,
84
    elevation: 8,
85
  },
86
  message: {
87
    color: '#fff',
88
    fontSize: 14,
89
    fontWeight: '500',
90
    lineHeight: 20,
91
  },
92
});