eletrotupi / tcc/ frontend/components/ui/Button.tsx8b59f8151ab8c986db903c1f9f856d47149e6204
3.2 KB | 152 lines Raw
1
import React from 'react';
2
import {
3
  TouchableOpacity,
4
  Text,
5
  StyleSheet,
6
  ActivityIndicator,
7
  TouchableOpacityProps,
8
  ViewStyle,
9
  TextStyle,
10
} from 'react-native';
11
import { useThemeColor } from '@/hooks/use-theme-color';
12

13
interface ButtonProps extends TouchableOpacityProps {
14
  title: string;
15
  variant?: 'primary' | 'secondary' | 'outline' | 'ghost';
16
  size?: 'small' | 'medium' | 'large';
17
  loading?: boolean;
18
  disabled?: boolean;
19
  style?: ViewStyle;
20
  textStyle?: TextStyle;
21
}
22

23
export const Button: React.FC<ButtonProps> = ({
24
  title,
25
  variant = 'primary',
26
  size = 'medium',
27
  loading = false,
28
  disabled = false,
29
  style,
30
  textStyle,
31
  onPress,
32
  ...props
33
}) => {
34
  const primaryColor = useThemeColor({}, 'tint');
35
  const textColor = useThemeColor({}, 'text');
36
  const backgroundColor = useThemeColor({}, 'background');
37
  const borderColor = useThemeColor({}, 'border');
38

39
  const getBackgroundColor = () => {
40
    if (disabled) return useThemeColor({ light: '#e5e5e5', dark: '#404040' }, 'background');
41
    switch (variant) {
42
      case 'primary':
43
        return primaryColor;
44
      case 'secondary':
45
        return useThemeColor({ light: '#f3f4f6', dark: '#374151' }, 'background');
46
      case 'outline':
47
      case 'ghost':
48
        return 'transparent';
49
      default:
50
        return primaryColor;
51
    }
52
  };
53

54
  const getTextColor = () => {
55
    if (disabled) return useThemeColor({}, 'text');
56
    switch (variant) {
57
      case 'primary':
58
      case 'secondary':
59
      case 'outline':
60
      case 'ghost':
61
        return textColor;
62
      default:
63
        return '#fff';
64
    }
65
  };
66

67
  const getBorderWidth = () => {
68
    return variant === 'outline' ? 1 : 0;
69
  };
70

71
  const getBorderColor = () => {
72
    if (variant === 'outline') {
73
      return disabled ? borderColor : primaryColor;
74
    }
75
    return 'transparent';
76
  };
77

78
  const getHeight = () => {
79
    switch (size) {
80
      case 'small':
81
        return 36;
82
      case 'medium':
83
        return 44;
84
      case 'large':
85
        return 52;
86
      default:
87
        return 44;
88
    }
89
  };
90

91
  const getFontSize = () => {
92
    switch (size) {
93
      case 'small':
94
        return 14;
95
      case 'medium':
96
        return 16;
97
      case 'large':
98
        return 18;
99
      default:
100
        return 16;
101
    }
102
  };
103

104
  return (
105
    <TouchableOpacity
106
      style={[
107
        styles.button,
108
        {
109
          backgroundColor: getBackgroundColor(),
110
          borderWidth: getBorderWidth(),
111
          borderColor: getBorderColor(),
112
          height: getHeight(),
113
          opacity: disabled || loading ? 0.6 : 1,
114
        },
115
        style,
116
      ]}
117
      disabled={disabled || loading}
118
      onPress={onPress}
119
      {...props}
120
    >
121
      {loading ? (
122
        <ActivityIndicator color={getTextColor()} />
123
      ) : (
124
        <Text
125
          style={[
126
            styles.text,
127
            {
128
              color: getTextColor(),
129
              fontSize: getFontSize(),
130
            },
131
            textStyle,
132
          ]}
133
        >
134
          {title}
135
        </Text>
136
      )}
137
    </TouchableOpacity>
138
  );
139
};
140

141
const styles = StyleSheet.create({
142
  button: {
143
    borderRadius: 8,
144
    paddingHorizontal: 20,
145
    alignItems: 'center',
146
    justifyContent: 'center',
147
    marginVertical: 8,
148
  },
149
  text: {
150
    fontWeight: '600',
151
  },
152
});