138 lines
2.8 KiB
TypeScript
138 lines
2.8 KiB
TypeScript
import {
|
|
Pressable,
|
|
StyleSheet,
|
|
Text,
|
|
type PressableProps,
|
|
type TextStyle,
|
|
ViewStyle,
|
|
} from 'react-native';
|
|
|
|
import { ThemedText } from '@/components/themed-text';
|
|
import { useThemeColor } from '@/hooks/use-theme-color';
|
|
|
|
export type ButtonVariant = 'primary' | 'secondary' | 'outline' | 'ghost';
|
|
export type ButtonSize = 'sm' | 'md' | 'lg';
|
|
|
|
interface ButtonProps extends PressableProps {
|
|
variant?: ButtonVariant;
|
|
size?: ButtonSize;
|
|
children: React.ReactNode;
|
|
textStyle?: TextStyle;
|
|
}
|
|
|
|
export function Button({
|
|
variant = 'primary',
|
|
size = 'md',
|
|
children,
|
|
style,
|
|
textStyle,
|
|
...props
|
|
}: ButtonProps) {
|
|
const backgroundColor = useThemeColor(
|
|
variantStyles[variant].background,
|
|
'tint'
|
|
);
|
|
const borderColor = useThemeColor(
|
|
variantStyles[variant].border,
|
|
'tint'
|
|
);
|
|
const textColor = useThemeColor(
|
|
variantStyles[variant].text,
|
|
'tint'
|
|
);
|
|
|
|
const dynamicStyles = {
|
|
backgroundColor,
|
|
borderColor,
|
|
borderWidth: variantStyles[variant].borderWidth,
|
|
};
|
|
|
|
return (
|
|
<Pressable
|
|
style={[
|
|
styles.base,
|
|
styles[size],
|
|
dynamicStyles,
|
|
style,
|
|
] as any}
|
|
{...props}
|
|
>
|
|
<ThemedText
|
|
style={[
|
|
styles.text,
|
|
styles[`${size}Text`],
|
|
{ color: textColor },
|
|
variant === 'ghost' && { paddingHorizontal: 0, paddingVertical: 0 },
|
|
textStyle,
|
|
]}
|
|
>
|
|
{children}
|
|
</ThemedText>
|
|
</Pressable>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
base: {
|
|
borderRadius: 8,
|
|
flexDirection: 'row',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
},
|
|
sm: {
|
|
paddingHorizontal: 12,
|
|
paddingVertical: 8,
|
|
minHeight: 36,
|
|
},
|
|
md: {
|
|
paddingHorizontal: 16,
|
|
paddingVertical: 12,
|
|
minHeight: 44,
|
|
},
|
|
lg: {
|
|
paddingHorizontal: 20,
|
|
paddingVertical: 16,
|
|
minHeight: 52,
|
|
},
|
|
text: {
|
|
fontWeight: '600',
|
|
textAlign: 'center',
|
|
},
|
|
smText: {
|
|
fontSize: 14,
|
|
},
|
|
mdText: {
|
|
fontSize: 16,
|
|
},
|
|
lgText: {
|
|
fontSize: 18,
|
|
},
|
|
});
|
|
|
|
const variantStyles = {
|
|
primary: {
|
|
background: { light: '#0a7ea4', dark: '#fff' },
|
|
text: { light: '#fff', dark: '#000' },
|
|
border: { light: 'transparent', dark: 'transparent' },
|
|
borderWidth: 0,
|
|
},
|
|
secondary: {
|
|
background: { light: '#f0f0f0', dark: '#2C2E2F' },
|
|
text: { light: '#11181C', dark: '#ECEDEE' },
|
|
border: { light: 'transparent', dark: 'transparent' },
|
|
borderWidth: 0,
|
|
},
|
|
outline: {
|
|
background: { light: 'transparent', dark: 'transparent' },
|
|
text: { light: '#0a7ea4', dark: '#fff' },
|
|
border: { light: '#0a7ea4', dark: '#fff' },
|
|
borderWidth: 1,
|
|
},
|
|
ghost: {
|
|
background: { light: 'transparent', dark: 'transparent' },
|
|
text: { light: '#0a7ea4', dark: '#fff' },
|
|
border: { light: 'transparent', dark: 'transparent' },
|
|
borderWidth: 0,
|
|
},
|
|
};
|