eletrotupi / tcc/ frontend/components/ui/Button.tsxa6c29bd016885a779e10d45eaf1d1cd6ea95d75c
3.2 KB | 153 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({ light: '#9ca3af', dark: '#6b7280' }, 'text');
56
    switch (variant) {
57
      case 'primary':
58
        return '#fff';
59
      case 'secondary':
60
      case 'outline':
61
      case 'ghost':
62
        return textColor;
63
      default:
64
        return '#fff';
65
    }
66
  };
67

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

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

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

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

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

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