100 lines
2.5 KiB
TypeScript
100 lines
2.5 KiB
TypeScript
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' | 'black' | 'darkGrey' | 'blue' | 'pink';
|
|
type LabelColor = ButtonColor | 'black';
|
|
type IconLocation = 'left' | 'right';
|
|
|
|
export 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: secondary ? theme.colors.fixed.white : theme.colors.fixed[bgColor],
|
|
borderWidth: 4,
|
|
borderColor: theme.colors.fixed[bgColor],
|
|
borderRadius: 0,
|
|
height: theme.layout.gridUnit * 20,
|
|
justifyContent: 'center',
|
|
paddingHorizontal: theme.layout.gridUnit * 4,
|
|
alignItems: 'center',
|
|
flexDirection: 'row',
|
|
}));
|
|
|
|
const Label = styled(Text)<{ color: LabelColor }>(({ theme, color }) => ({
|
|
color: theme.colors.fixed[color],
|
|
fontSize: 16,
|
|
fontWeight: 'semibold',
|
|
}));
|
|
|
|
const SecondaryLabel = styled(Text)<{ bgColor: ButtonColor }>(({ theme, bgColor }) => ({
|
|
color: theme.colors.fixed[bgColor],
|
|
fontWeight: 'semibold',
|
|
}));
|
|
|
|
const IconContainer = styled.View(({ theme }) => ({
|
|
height: theme.layout.iconSize.medium,
|
|
aspectRatio: 1,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
}));
|