boxons/components/shared/Button.tsx

100 lines
2.5 KiB
TypeScript
Raw Normal View History

2024-10-13 11:29:36 +00:00
import React, { useCallback } from 'react';
import styled from '@emotion/native';
import { HorizontalSpacer } from '@/components/shared/Spacers';
import { Text } from '@/components/shared/Themed';
type ButtonColor = 'green' | 'red' | 'grey' | 'white';
type LabelColor = ButtonColor | 'black';
type IconLocation = 'left' | 'right';
interface ButtonProps {
label?: string;
color?: ButtonColor;
labelColor?: LabelColor;
status?: 'ready' | 'disabled' | 'loading';
onPress?: () => void;
secondary?: boolean;
iconLocation?: IconLocation;
icon?: any;
}
const Button: React.FC<ButtonProps> = ({
label,
color = 'white',
labelColor = 'black',
status = 'ready',
onPress,
secondary = false,
icon = undefined,
iconLocation = 'right'
}: ButtonProps) => {
const safeOnPress = useCallback(() => onPress?.(), [onPress]);
return (
<Container
secondary={secondary}
bgColor={color}
onPress={safeOnPress}
disabled={status !== 'ready'}
>
{icon && iconLocation === 'left' && (
<>
<IconContainer>{icon}</IconContainer>
{label && <HorizontalSpacer widthUnits={2} />}
</>
)}
{secondary ? (
<SecondaryLabel bgColor={color}>{label}</SecondaryLabel>
) : (
<Label color={labelColor}>{label}</Label>
)}
{icon && iconLocation === 'right' && (
<>
{label && <HorizontalSpacer widthUnits={2} />}
<IconContainer>{icon}</IconContainer>
</>
)}
</Container>
);
};
export default Button;
const Container = styled.TouchableOpacity<{
bgColor: ButtonColor;
disabled: boolean;
secondary: boolean;
}>(({ theme, bgColor, secondary }) => ({
backgroundColor: theme.colors.fixed[bgColor],
2024-10-13 11:29:36 +00:00
borderWidth: secondary ? 1 : 0,
borderColor: theme.colors.fixed[bgColor],
2024-10-13 11:29:36 +00:00
borderRadius: 6,
height: theme.layout.gridUnit * 12,
justifyContent: 'center',
paddingHorizontal: theme.layout.gridUnit * 4,
alignItems: 'center',
flexDirection: 'row',
}));
const Label = styled(Text)<{ color: LabelColor }>(({ theme, color }) => ({
color: theme.colors.fixed[color],
2024-10-13 11:29:36 +00:00
fontSize: 16,
fontWeight: 'semibold',
}));
const SecondaryLabel = styled(Text)<{ bgColor: ButtonColor }>(({ theme, bgColor }) => ({
color: theme.colors.fixed[bgColor],
2024-10-13 11:29:36 +00:00
fontWeight: 'semibold',
}));
const IconContainer = styled.View(({ theme }) => ({
height: theme.layout.iconSize.medium,
aspectRatio: 1,
alignItems: 'center',
justifyContent: 'center',
}));