Files
Nova40/src/components/Button.js
T
dios.one 23dc306f12 init
2026-04-21 18:00:30 +07:00

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,
},
});