2020-05-15 14:29:27 +02:00
|
|
|
import React, { useRef } from 'react';
|
2020-02-13 23:43:20 +01:00
|
|
|
import PropTypes from 'prop-types';
|
2020-02-19 23:45:17 +01:00
|
|
|
import classnames from 'classnames';
|
2020-02-13 23:43:20 +01:00
|
|
|
|
2020-03-04 23:16:51 +01:00
|
|
|
const baseClasses =
|
2020-04-13 18:48:45 +02:00
|
|
|
'leading-none font-sans text-center justify-center items-center outline-none transition duration-300 ease-in-out focus:outline-none';
|
2020-03-04 23:16:51 +01:00
|
|
|
|
2020-02-13 23:43:20 +01:00
|
|
|
const defaults = {
|
|
|
|
|
color: 'default',
|
2020-03-02 19:37:00 +01:00
|
|
|
disabled: false,
|
2020-05-15 14:29:27 +02:00
|
|
|
fullWidth: false,
|
|
|
|
|
rounded: 'medium',
|
|
|
|
|
size: 'medium',
|
2020-02-13 23:43:20 +01:00
|
|
|
type: 'button',
|
2020-05-15 14:29:27 +02:00
|
|
|
variant: 'contained',
|
2020-02-13 23:43:20 +01:00
|
|
|
};
|
|
|
|
|
|
2020-05-15 14:29:27 +02:00
|
|
|
const roundedClasses = {
|
2020-02-19 23:45:17 +01:00
|
|
|
none: '',
|
2020-05-15 14:29:27 +02:00
|
|
|
small: 'rounded',
|
2020-02-13 23:43:20 +01:00
|
|
|
medium: 'rounded-md',
|
|
|
|
|
large: 'rounded-lg',
|
|
|
|
|
full: 'rounded-full',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const variantClasses = {
|
|
|
|
|
text: {
|
2020-03-04 23:16:51 +01:00
|
|
|
default:
|
2020-04-02 20:52:41 +02:00
|
|
|
'text-primary-light hover:bg-primary-light hover:text-white active:opacity-80 focus:bg-primary-light focus:text-white',
|
2020-03-04 23:16:51 +01:00
|
|
|
primary:
|
2020-04-02 20:52:41 +02:00
|
|
|
'text-primary-main hover:bg-primary-main hover:text-white active:opacity-80 focus:bg-primary-main focus:text-white',
|
2020-03-04 23:16:51 +01:00
|
|
|
secondary:
|
2020-04-02 20:52:41 +02:00
|
|
|
'text-secondary-light hover:bg-secondary-light hover:text-white active:opacity-80 focus:bg-secondary-light focus:text-white',
|
2020-03-04 23:16:51 +01:00
|
|
|
white:
|
|
|
|
|
'text-white hover:bg-white hover:text-black active:opacity-80 focus:bg-white focus:text-black',
|
2020-07-03 03:41:55 +02:00
|
|
|
black:
|
|
|
|
|
'text-black hover:bg-black hover:text-white focus:bg-black focus:text-white active:opacity-80',
|
2020-02-13 23:43:20 +01:00
|
|
|
},
|
|
|
|
|
outlined: {
|
2020-03-04 23:16:51 +01:00
|
|
|
default:
|
2020-04-02 20:52:41 +02:00
|
|
|
'border bg-trasparent border-primary-light text-primary-light hover:bg-primary-light hover:text-black focus:text-black focus:bg-primary-light active:opacity-80',
|
2020-03-04 23:16:51 +01:00
|
|
|
primary:
|
2020-04-02 20:52:41 +02:00
|
|
|
'border bg-transparent border-primary-main text-primary-main hover:opacity-80 active:opacity-100 focus:opacity-80',
|
2020-03-04 23:16:51 +01:00
|
|
|
secondary:
|
2020-04-02 20:52:41 +02:00
|
|
|
'border bg-transparent border-secondary-light text-secondary-light hover:opacity-80 active:opacity-100 focus:opacity-80',
|
2020-03-04 23:16:51 +01:00
|
|
|
white:
|
|
|
|
|
'border bg-transparent border-white text-white hover:opacity-80 active:opacity-100 focus:opacity-80',
|
2020-07-03 03:41:55 +02:00
|
|
|
black:
|
|
|
|
|
'border bg-black border-primary-main text-white hover:bg-primary-main focus:bg-primary-main hover:border-black focus:border-black',
|
2020-02-13 23:43:20 +01:00
|
|
|
},
|
|
|
|
|
contained: {
|
2020-03-04 23:16:51 +01:00
|
|
|
default:
|
2020-04-02 20:52:41 +02:00
|
|
|
'bg-primary-light text-black hover:opacity-80 active:opacity-100 focus:opacity-80',
|
2020-03-04 23:16:51 +01:00
|
|
|
primary:
|
2020-04-02 20:52:41 +02:00
|
|
|
'bg-primary-main text-white hover:opacity-80 active:opacity-100 focus:opacity-80',
|
2020-03-04 23:16:51 +01:00
|
|
|
secondary:
|
2020-04-02 20:52:41 +02:00
|
|
|
'bg-secondary-light text-white hover:opacity-80 active:opacity-100 focus:opacity-80',
|
2020-03-04 23:16:51 +01:00
|
|
|
white:
|
|
|
|
|
'bg-white text-black hover:opacity-80 active:opacity-100 focus:opacity-80',
|
2020-07-03 03:41:55 +02:00
|
|
|
black:
|
|
|
|
|
'bg-black text-white hover:opacity-80 active:opacity-100 focus:opacity-80',
|
2020-08-19 21:02:59 +02:00
|
|
|
light:
|
|
|
|
|
'border bg-primary-light border-primary-light text-black hover:opacity-80 active:opacity-100 focus:opacity-80',
|
2020-02-13 23:43:20 +01:00
|
|
|
},
|
2021-08-30 15:36:05 +02:00
|
|
|
disabled: {
|
2022-02-10 20:08:34 +01:00
|
|
|
default: 'cursor-not-allowed opacity-50 bg-primary-light text-black',
|
|
|
|
|
primary: 'cursor-not-allowed opacity-50 bg-primary-main text-white',
|
|
|
|
|
secondary: 'cursor-not-allowed opacity-50 bg-secondary-light text-white',
|
|
|
|
|
white: 'cursor-not-allowed opacity-50 bg-white text-black',
|
|
|
|
|
black: 'cursor-not-allowed opacity-50 bg-black text-white',
|
2021-08-30 15:36:05 +02:00
|
|
|
light:
|
|
|
|
|
'cursor-not-allowed opacity-50 border bg-primary-light border-primary-light text-black',
|
|
|
|
|
},
|
2020-02-13 23:43:20 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const sizeClasses = {
|
2020-04-13 18:48:45 +02:00
|
|
|
small: 'py-2 px-2 text-sm min-w-md',
|
|
|
|
|
medium: 'py-2 px-2 text-lg min-w-md',
|
|
|
|
|
large: 'py-2 px-6 text-xl min-w-md',
|
2020-04-10 01:31:21 +02:00
|
|
|
initial: '',
|
2020-03-04 23:16:51 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const fullWidthClasses = {
|
|
|
|
|
true: 'flex w-full',
|
|
|
|
|
false: 'inline-flex',
|
2020-02-13 23:43:20 +01:00
|
|
|
};
|
|
|
|
|
|
2020-02-19 23:45:17 +01:00
|
|
|
const Button = ({
|
|
|
|
|
children,
|
|
|
|
|
variant = defaults.variant,
|
|
|
|
|
color = defaults.color,
|
|
|
|
|
size = defaults.size,
|
2020-05-15 14:29:27 +02:00
|
|
|
rounded = defaults.rounded,
|
2020-02-19 23:45:17 +01:00
|
|
|
disabled = defaults.disabled,
|
|
|
|
|
type = defaults.type,
|
2020-03-02 20:10:51 +01:00
|
|
|
fullWidth = defaults.fullWidth,
|
2020-02-19 23:45:17 +01:00
|
|
|
startIcon: startIconProp,
|
|
|
|
|
endIcon: endIconProp,
|
2021-03-01 16:52:54 +01:00
|
|
|
name,
|
2020-02-19 23:45:17 +01:00
|
|
|
className,
|
2020-07-03 05:26:06 +02:00
|
|
|
onClick,
|
|
|
|
|
/** TODO: All possible props should be explicitly defined -- avoid spreading props */
|
2020-02-19 23:45:17 +01:00
|
|
|
...rest
|
|
|
|
|
}) => {
|
2020-03-02 19:37:00 +01:00
|
|
|
const startIcon = startIconProp && (
|
2020-05-15 14:29:27 +02:00
|
|
|
<div className="mr-2">
|
|
|
|
|
{React.cloneElement(startIconProp, {
|
|
|
|
|
className: classnames('w-4 h-4 fill-current'),
|
|
|
|
|
})}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const endIcon = endIconProp && (
|
|
|
|
|
<div className="ml-2">
|
|
|
|
|
{React.cloneElement(endIconProp, {
|
|
|
|
|
className: classnames('w-4 h-4 fill-current'),
|
|
|
|
|
})}
|
|
|
|
|
</div>
|
2020-02-19 23:45:17 +01:00
|
|
|
);
|
2020-05-15 14:29:27 +02:00
|
|
|
const buttonElement = useRef(null);
|
2020-02-19 23:45:17 +01:00
|
|
|
|
2020-07-03 03:41:55 +02:00
|
|
|
const handleOnClick = e => {
|
2020-04-02 20:52:41 +02:00
|
|
|
buttonElement.current.blur();
|
2020-07-03 05:26:06 +02:00
|
|
|
if (!disabled) {
|
|
|
|
|
onClick(e);
|
2020-04-02 20:52:41 +02:00
|
|
|
}
|
|
|
|
|
};
|
2020-02-19 23:45:17 +01:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<button
|
|
|
|
|
className={classnames(
|
2020-03-12 17:26:31 +01:00
|
|
|
className,
|
2020-02-19 23:45:17 +01:00
|
|
|
baseClasses,
|
|
|
|
|
variantClasses[variant][color],
|
2020-05-15 14:29:27 +02:00
|
|
|
roundedClasses[rounded],
|
2020-02-19 23:45:17 +01:00
|
|
|
sizeClasses[size],
|
2022-02-10 20:08:34 +01:00
|
|
|
fullWidthClasses[fullWidth]
|
2020-02-19 23:45:17 +01:00
|
|
|
)}
|
2021-08-30 15:36:05 +02:00
|
|
|
disabled={disabled}
|
2020-05-15 14:29:27 +02:00
|
|
|
ref={buttonElement}
|
|
|
|
|
onClick={handleOnClick}
|
2020-02-19 23:45:17 +01:00
|
|
|
type={type}
|
2021-03-01 16:52:54 +01:00
|
|
|
data-cy={`${name}-btn`}
|
2020-02-19 23:45:17 +01:00
|
|
|
{...rest}
|
|
|
|
|
>
|
|
|
|
|
{startIcon}
|
|
|
|
|
{children}
|
|
|
|
|
{endIcon}
|
|
|
|
|
</button>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
2022-02-10 20:08:34 +01:00
|
|
|
Button.defaultProps = {
|
|
|
|
|
color: defaults.color,
|
|
|
|
|
disabled: false,
|
|
|
|
|
children: '',
|
|
|
|
|
onClick: () => {},
|
|
|
|
|
};
|
|
|
|
|
|
2020-02-13 23:43:20 +01:00
|
|
|
Button.propTypes = {
|
2022-02-10 20:08:34 +01:00
|
|
|
/** What is inside the button, can be text or react component */
|
2020-02-14 23:46:27 +01:00
|
|
|
children: PropTypes.node,
|
2022-02-10 20:08:34 +01:00
|
|
|
/** Callback to be called when the button is clicked */
|
|
|
|
|
onClick: PropTypes.func.isRequired,
|
|
|
|
|
/** Button size */
|
2020-07-24 12:51:57 +02:00
|
|
|
size: PropTypes.oneOf(['small', 'medium', 'large', 'initial', 'inherit']),
|
2022-02-10 20:08:34 +01:00
|
|
|
/** Button corner roundness */
|
2020-04-10 01:31:21 +02:00
|
|
|
rounded: PropTypes.oneOf(['none', 'small', 'medium', 'large', 'full']),
|
2022-07-27 18:39:04 +02:00
|
|
|
variant: PropTypes.oneOf(['text', 'outlined', 'contained', 'disabled']),
|
2020-03-12 17:26:31 +01:00
|
|
|
color: PropTypes.oneOf([
|
|
|
|
|
'default',
|
|
|
|
|
'primary',
|
|
|
|
|
'secondary',
|
|
|
|
|
'white',
|
2020-07-03 03:41:55 +02:00
|
|
|
'black',
|
2020-03-12 17:26:31 +01:00
|
|
|
'inherit',
|
2022-02-10 20:08:34 +01:00
|
|
|
'light',
|
2020-03-12 17:26:31 +01:00
|
|
|
]),
|
2022-02-10 20:08:34 +01:00
|
|
|
/** Whether the button should have full width */
|
2020-03-12 17:26:31 +01:00
|
|
|
fullWidth: PropTypes.bool,
|
2022-02-10 20:08:34 +01:00
|
|
|
/** Whether the button should be disabled */
|
2020-02-14 23:46:27 +01:00
|
|
|
disabled: PropTypes.bool,
|
2022-02-10 20:08:34 +01:00
|
|
|
/** Button type */
|
2020-02-14 23:46:27 +01:00
|
|
|
type: PropTypes.string,
|
2021-03-01 16:52:54 +01:00
|
|
|
name: PropTypes.string,
|
2022-02-10 20:08:34 +01:00
|
|
|
/** Button start icon name - if any icon is specified */
|
2020-02-14 23:46:27 +01:00
|
|
|
startIcon: PropTypes.node,
|
2022-02-10 20:08:34 +01:00
|
|
|
/** Button end icon name - if any icon is specified */
|
2020-02-14 23:46:27 +01:00
|
|
|
endIcon: PropTypes.node,
|
2022-02-10 20:08:34 +01:00
|
|
|
/** Additional TailwindCSS classnames */
|
2020-03-03 23:36:22 +01:00
|
|
|
className: PropTypes.string,
|
2020-02-13 23:43:20 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default Button;
|