1import { borderRadius } from '@expo/styleguide-native'; 2import { ExpoTheme, scale, Text, useExpoTheme } from 'expo-dev-client-components'; 3import React from 'react'; 4import { ActivityIndicator, TouchableOpacity, ViewStyle } from 'react-native'; 5 6type Theme = 'primary' | 'secondary' | 'tertiary' | 'ghost' | 'error'; 7 8type Props = { 9 label: string; 10 onPress: () => void; 11 theme?: Theme; 12 disabled?: boolean; 13 loading?: boolean; 14 style?: ViewStyle; 15}; 16 17function getThemeColors( 18 theme: Theme, 19 expoTheme: ExpoTheme 20): { backgroundColor: string; borderColor?: string; borderWidth?: 1; color: string } { 21 switch (theme) { 22 case 'primary': 23 return { 24 backgroundColor: expoTheme.button.primary.background, 25 color: expoTheme.button.primary.foreground, 26 }; 27 case 'secondary': 28 return { 29 backgroundColor: expoTheme.button.secondary.background, 30 color: expoTheme.button.secondary.foreground, 31 }; 32 case 'tertiary': 33 return { 34 backgroundColor: expoTheme.button.tertiary.background, 35 color: expoTheme.button.tertiary.foreground, 36 }; 37 case 'ghost': 38 return { 39 backgroundColor: expoTheme.button.ghost.background, 40 color: expoTheme.button.ghost.foreground, 41 borderColor: expoTheme.button.ghost.border, 42 borderWidth: 1, 43 }; 44 case 'error': 45 return { 46 backgroundColor: expoTheme.background.error, 47 color: expoTheme.text.error, 48 borderColor: expoTheme.border.error, 49 borderWidth: 1, 50 }; 51 } 52} 53 54export function Button({ label, theme = 'tertiary', onPress, loading, disabled, style }: Props) { 55 const expoTheme = useExpoTheme(); 56 57 const { backgroundColor, borderColor, borderWidth, color } = getThemeColors(theme, expoTheme); 58 59 return ( 60 <TouchableOpacity 61 style={[ 62 { 63 backgroundColor, 64 borderRadius: borderRadius.medium, 65 paddingVertical: scale.small, 66 borderColor, 67 borderWidth, 68 paddingHorizontal: scale.medium, 69 opacity: disabled ? 0.5 : 1, 70 }, 71 style, 72 ]} 73 disabled={disabled} 74 onPress={onPress}> 75 {loading ? ( 76 <ActivityIndicator /> 77 ) : ( 78 <Text type="InterSemiBold" style={{ color }}> 79 {label} 80 </Text> 81 )} 82 </TouchableOpacity> 83 ); 84} 85