hasari-api / apps /mobile /components /UploadButton.tsx
erdoganpeker's picture
v0.3.0 — multimodal vehicle damage MVP
e327f0d
import React from 'react';
import {
ActivityIndicator,
Pressable,
StyleProp,
StyleSheet,
Text,
View,
ViewStyle,
} from 'react-native';
import { colors, radius, spacing, typography } from '../theme';
interface Props {
label: string;
onPress: () => void;
variant?: 'primary' | 'secondary' | 'danger' | 'ghost';
disabled?: boolean;
loading?: boolean;
icon?: string; // emoji
style?: StyleProp<ViewStyle>;
}
export default function UploadButton({
label,
onPress,
variant = 'primary',
disabled,
loading,
icon,
style,
}: Props) {
const isDisabled = disabled || loading;
return (
<Pressable
accessibilityRole="button"
accessibilityState={{ disabled: isDisabled }}
onPress={onPress}
disabled={isDisabled}
style={({ pressed }) => [
styles.base,
styles[variant],
pressed && !isDisabled && styles.pressed,
isDisabled && styles.disabled,
style,
]}
>
<View style={styles.content}>
{loading ? (
<ActivityIndicator color={variant === 'secondary' ? colors.text : '#fff'} />
) : (
<>
{icon ? <Text style={styles.icon}>{icon}</Text> : null}
<Text style={[styles.label, variant === 'secondary' && styles.labelSecondary]}>
{label}
</Text>
</>
)}
</View>
</Pressable>
);
}
const styles = StyleSheet.create({
base: {
minHeight: 48,
paddingHorizontal: spacing.xl,
paddingVertical: spacing.md,
borderRadius: radius.md,
justifyContent: 'center',
alignItems: 'center',
},
content: {
flexDirection: 'row',
alignItems: 'center',
gap: spacing.sm,
},
primary: { backgroundColor: colors.primary },
secondary: {
backgroundColor: 'transparent',
borderWidth: 1,
borderColor: colors.borderMuted,
},
danger: { backgroundColor: colors.danger },
ghost: { backgroundColor: 'transparent' },
pressed: { opacity: 0.85 },
disabled: { opacity: 0.5 },
icon: { fontSize: 18, marginRight: spacing.xs, color: '#fff' },
label: {
...typography.bodyBold,
color: '#fff',
},
labelSecondary: {
color: colors.text,
},
});