Files
biiproject-kit-v1/mobile/components/Button.tsx
T

93 lines
2.4 KiB
TypeScript

import React from 'react';
import { TouchableOpacity, Text, StyleSheet, ViewStyle, TextStyle, ActivityIndicator, StyleProp } from 'react-native';
import * as Haptics from 'expo-haptics';
import { useAppTheme } from '../context/ThemeContext';
interface ButtonProps {
onPress: () => void;
title: string;
variant?: 'primary' | 'secondary' | 'outline' | 'error';
style?: StyleProp<ViewStyle>;
textStyle?: StyleProp<TextStyle>;
disabled?: boolean;
loading?: boolean;
}
const LIME = '#C6F135';
export const Button: React.FC<ButtonProps> = ({
onPress,
title,
variant = 'primary',
style,
textStyle,
disabled,
loading
}) => {
const { colors, isDark } = useAppTheme();
const handlePress = () => {
if (disabled || loading) return;
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
onPress();
};
const getBackgroundColor = () => {
if (disabled || loading) return isDark ? '#222' : '#EEE';
switch (variant) {
case 'primary': return isDark ? LIME : '#1A1A1A';
case 'secondary': return isDark ? '#2A2A2A' : '#F5F5F5';
case 'outline': return 'transparent';
case 'error': return '#EF4444';
default: return isDark ? LIME : '#1A1A1A';
}
};
const getTextColor = () => {
if (disabled || loading) return isDark ? '#444' : '#BBB';
switch (variant) {
case 'outline': return isDark ? LIME : '#1A1A1A';
case 'primary': return isDark ? '#1A1A1A' : '#FFFFFF';
case 'secondary': return colors.text;
case 'error': return '#FFFFFF';
default: return isDark ? '#1A1A1A' : '#FFFFFF';
}
};
return (
<TouchableOpacity
onPress={handlePress}
activeOpacity={0.85}
disabled={disabled || loading}
style={[
styles.button,
{ backgroundColor: getBackgroundColor() },
variant === 'outline' && { borderWidth: 1.5, borderColor: isDark ? LIME : '#1A1A1A' },
style
]}
>
{loading ? (
<ActivityIndicator color={getTextColor()} />
) : (
<Text style={[styles.text, { color: getTextColor() }, textStyle]}>
{title}
</Text>
)}
</TouchableOpacity>
);
};
const styles = StyleSheet.create({
button: {
height: 58,
borderRadius: 16,
justifyContent: 'center',
alignItems: 'center',
paddingHorizontal: 24,
},
text: {
fontSize: 16,
fontFamily: 'Outfit_700Bold',
},
});