zepio/app/components/button.js

124 lines
2.7 KiB
JavaScript
Raw Normal View History

2018-12-05 10:14:30 -08:00
// @flow
2019-02-04 20:41:45 -08:00
import React, { type ElementProps } from 'react';
2018-12-05 10:14:30 -08:00
import styled from 'styled-components';
import { Link } from 'react-router-dom';
2018-12-20 06:10:25 -08:00
const DefaultButton = styled.button`
2019-01-24 06:56:49 -08:00
align-items: center;
display: flex;
justify-content: center;
2018-12-05 10:14:30 -08:00
padding: 10px 30px;
font-family: ${props => props.theme.fontFamily};
font-weight: ${props => String(props.theme.fontWeight.bold)};
font-size: ${props => `${props.theme.fontSize.regular}em`};
2018-12-05 10:14:30 -08:00
cursor: pointer;
outline: none;
min-width: 100px;
border-radius: 100px;
transition: background-color 0.1s ${props => props.theme.transitionEase};
2018-12-05 10:14:30 -08:00
`;
2019-01-29 07:03:04 -08:00
const Primary = styled(DefaultButton)`
background-color: ${props => props.theme.colors.primary};
color: ${props => props.theme.colors.secondary};
2018-12-05 10:14:30 -08:00
border: none;
&:hover {
opacity: 0.9;
2018-12-05 10:14:30 -08:00
}
&:disabled {
background-color: ${props => props.theme.colors.buttonBorderColor};
2018-12-05 10:14:30 -08:00
cursor: not-allowed;
opacity: 0.8;
}
`;
2019-01-29 07:03:04 -08:00
const Secondary = styled(DefaultButton)`
2018-12-20 06:10:25 -08:00
background-color: transparent;
color: ${props => props.theme.colors.secondary};
border: 2px solid ${props => props.theme.colors.buttonBorderColor};
2018-12-05 10:14:30 -08:00
&:hover {
border-color: ${props => props.theme.colors.primary};
2018-12-05 10:14:30 -08:00
}
&:disabled {
background-color: Transparent;
cursor: not-allowed;
color: ${props => props.theme.colors.buttonBorderColor};
2018-12-05 10:14:30 -08:00
&:hover {
border-color: ${props => props.theme.colors.buttonBorderColor};
2018-12-05 10:14:30 -08:00
}
}
`;
const Icon = styled.img`
2019-01-24 06:56:49 -08:00
height: 12px;
width: 12px;
margin-right: 10px;
`;
2018-12-05 10:14:30 -08:00
type Props = {
...ElementProps<'button'>,
2018-12-05 10:14:30 -08:00
label: string,
onClick?: () => void,
2019-01-12 09:55:05 -08:00
to?: ?string,
2018-12-05 10:14:30 -08:00
variant?: 'primary' | 'secondary',
disabled?: boolean,
icon?: string | null,
2018-12-20 06:10:25 -08:00
className?: string,
2018-12-21 07:42:31 -08:00
isLoading?: boolean,
2019-01-29 07:03:04 -08:00
id?: string,
2018-12-05 10:14:30 -08:00
};
export const Button = ({
2018-12-20 06:10:25 -08:00
onClick,
label,
to,
variant,
disabled,
icon,
2018-12-20 06:10:25 -08:00
className,
2018-12-21 07:42:31 -08:00
isLoading,
2019-01-23 09:04:11 -08:00
id,
2018-12-05 10:14:30 -08:00
}: Props) => {
if (to && onClick) throw new Error('Should define either "to" or "onClick"');
2018-12-05 10:14:30 -08:00
const props = {
onClick,
disabled: disabled || isLoading,
icon: null,
className,
2019-01-23 09:04:11 -08:00
id,
};
2018-12-21 07:42:31 -08:00
const buttonLabel = isLoading ? 'Loading...' : label;
2018-12-05 10:14:30 -08:00
const component = variant === 'primary' ? (
<Primary {...props} data-testid='PrimaryButton'>
{icon ? <Icon src={icon} /> : null}
{buttonLabel}
</Primary>
2018-12-05 10:14:30 -08:00
) : (
<Secondary {...props} data-testid='SecondaryButton'>
{icon ? <Icon src={icon} /> : null}
{buttonLabel}
</Secondary>
2018-12-05 10:14:30 -08:00
);
return to ? <Link to={String(to)}>{component}</Link> : component;
2018-12-05 10:14:30 -08:00
};
Button.defaultProps = {
to: '',
icon: null,
2018-12-05 10:14:30 -08:00
variant: 'primary',
onClick: () => {},
2018-12-05 10:14:30 -08:00
disabled: false,
2018-12-20 06:10:25 -08:00
className: '',
2018-12-21 07:42:31 -08:00
isLoading: false,
2019-01-29 07:03:04 -08:00
id: '',
2018-12-05 10:14:30 -08:00
};