expo-popcore-old/components/ui/button.tsx

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,
},
};