94 lines
2.1 KiB
JavaScript
94 lines
2.1 KiB
JavaScript
import React, { useRef } from 'react';
|
|
import { Animated, Text, StyleSheet, ActivityIndicator, Pressable } from 'react-native';
|
|
import { colors, fonts, borderRadius, spacing } from '../utils/theme';
|
|
|
|
export default function Button({
|
|
title,
|
|
onPress,
|
|
variant = 'primary',
|
|
loading = false,
|
|
disabled = false,
|
|
style,
|
|
}) {
|
|
const isPrimary = variant === 'primary';
|
|
const scale = useRef(new Animated.Value(1)).current;
|
|
|
|
const onPressIn = () => {
|
|
Animated.spring(scale, {
|
|
toValue: 0.93,
|
|
useNativeDriver: true,
|
|
speed: 50,
|
|
bounciness: 4,
|
|
}).start();
|
|
};
|
|
|
|
const onPressOut = () => {
|
|
Animated.spring(scale, {
|
|
toValue: 1,
|
|
useNativeDriver: true,
|
|
speed: 12,
|
|
bounciness: 8,
|
|
}).start();
|
|
};
|
|
|
|
return (
|
|
<Animated.View style={[{ transform: [{ scale }] }, style]}>
|
|
<Pressable
|
|
style={[
|
|
styles.button,
|
|
isPrimary ? styles.primary : styles.secondary,
|
|
disabled && styles.disabled,
|
|
]}
|
|
onPress={onPress}
|
|
onPressIn={onPressIn}
|
|
onPressOut={onPressOut}
|
|
disabled={disabled || loading}
|
|
>
|
|
{loading ? (
|
|
<ActivityIndicator color={colors.text} />
|
|
) : (
|
|
<Text style={[styles.text, !isPrimary && styles.secondaryText]}>
|
|
{title}
|
|
</Text>
|
|
)}
|
|
</Pressable>
|
|
</Animated.View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
button: {
|
|
paddingVertical: spacing.md,
|
|
paddingHorizontal: spacing.xl,
|
|
borderRadius: borderRadius.lg,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
minHeight: 52,
|
|
},
|
|
primary: {
|
|
backgroundColor: colors.primary,
|
|
shadowColor: colors.primary,
|
|
shadowOffset: { width: 0, height: 4 },
|
|
shadowOpacity: 0.4,
|
|
shadowRadius: 12,
|
|
elevation: 6,
|
|
},
|
|
secondary: {
|
|
backgroundColor: 'transparent',
|
|
borderWidth: 1.5,
|
|
borderColor: colors.primary,
|
|
},
|
|
disabled: {
|
|
opacity: 0.5,
|
|
},
|
|
text: {
|
|
color: colors.text,
|
|
fontSize: fonts.sizes.md,
|
|
fontWeight: fonts.weights.semibold,
|
|
textAlign: 'center',
|
|
},
|
|
secondaryText: {
|
|
color: colors.primary,
|
|
},
|
|
});
|