65 lines
1.7 KiB
TypeScript
65 lines
1.7 KiB
TypeScript
import React, { useRef } from "react";
|
|
import { View, Text, StyleSheet, Animated, TouchableWithoutFeedback } from "react-native";
|
|
import LinearGradient from "react-native-linear-gradient";
|
|
import { Ionicons } from "@react-native-vector-icons/ionicons";
|
|
import colors from "../colors";
|
|
|
|
type CardProps = {
|
|
title: string;
|
|
subtitle?: string;
|
|
iconName?: string;
|
|
onPress?: () => void;
|
|
backOne?: string;
|
|
backTwo?: string;
|
|
};
|
|
|
|
const AnimatedCard: React.FC<CardProps> = ({
|
|
title,
|
|
subtitle,
|
|
iconName = "ellipse-outline",
|
|
onPress,
|
|
backOne = colors.primary,
|
|
backTwo = colors.pastelPink,
|
|
}) => {
|
|
const scale = useRef(new Animated.Value(1)).current;
|
|
|
|
const handlePress = () => {
|
|
Animated.sequence([
|
|
Animated.spring(scale, { toValue: 0.95, useNativeDriver: true }),
|
|
]).start(() => onPress && onPress());
|
|
};
|
|
|
|
return (
|
|
<TouchableWithoutFeedback onPress={handlePress}>
|
|
<Animated.View style={[styles.card, { transform: [{ scale }] }]}>
|
|
<LinearGradient colors={[backOne, backTwo]} style={styles.gradient}>
|
|
<Ionicons name={iconName} size={38} color="#fff" style={styles.icon} />
|
|
<Text style={styles.title}>{title}</Text>
|
|
{subtitle && <Text style={styles.subtitle}>{subtitle}</Text>}
|
|
</LinearGradient>
|
|
</Animated.View>
|
|
</TouchableWithoutFeedback>
|
|
);
|
|
};
|
|
|
|
const styles = StyleSheet.create({
|
|
card: {
|
|
flex: 1,
|
|
height: 160,
|
|
margin: 8,
|
|
borderRadius: 20,
|
|
overflow: "hidden",
|
|
elevation: 5,
|
|
},
|
|
gradient: {
|
|
flex: 1,
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
},
|
|
icon: { marginBottom: 10 },
|
|
title: { fontSize: 18, fontWeight: "bold", color: "#fff" },
|
|
subtitle: { fontSize: 13, color: "#fff", opacity: 0.9 },
|
|
});
|
|
|
|
export default AnimatedCard;
|