feat: Button Component

This commit is contained in:
Rodrigo Antinarelli 2020-02-28 15:31:42 -03:00 committed by James A. Petts
parent 4a24bcbeb5
commit 36d5a46028
4 changed files with 350 additions and 88 deletions

View File

@ -1,19 +1,23 @@
import React from 'react';
import React, { useRef } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
const baseClasses =
'text-center items-center outline-none transition duration-300 ease-in-out font-bold focus:outline-none';
const defaults = {
variant: 'contained',
color: 'default',
size: 'medium',
radius: 'medium',
disabled: false,
fullWidth: false,
rounded: 'medium',
size: 'medium',
type: 'button',
variant: 'contained',
};
const radiusClasses = {
const roundedClasses = {
none: '',
small: 'rounded-sm',
small: 'rounded',
medium: 'rounded-md',
large: 'rounded-lg',
full: 'rounded-full',
@ -26,26 +30,46 @@ const disabledClasses = {
const variantClasses = {
text: {
default: 'hover:bg-gray-200 text-black',
primary: 'hover:bg-blue-100 text-blue-900',
secondary: 'hover:bg-blue-100 text-blue-300',
default:
'text-primary-light hover:bg-primary-light hover:text-white active:opacity-80 focus:bg-primary-light focus:text-white',
primary:
'text-primary-main hover:bg-primary-main hover:text-white active:opacity-80 focus:bg-primary-main focus:text-white',
secondary:
'text-darkBlue-100 hover:bg-darkBlue-100 hover:text-white active:opacity-80 focus:bg-darkBlue-100 focus:text-white',
white:
'text-white hover:bg-white hover:text-black active:opacity-80 focus:bg-white focus:text-black',
},
outlined: {
default: 'border border-black text-black hover:bg-gray-200',
primary: 'border border-blue-900 text-blue-900 hover:bg-blue-100',
secondary: 'border border-blue-300 text-blue-300 hover:bg-blue-100',
default:
'border bg-trasparent border-primary-light text-primary-light hover:opacity-80 active:opacity-100 focus:opacity-80',
primary:
'border bg-transparent border-primary-main text-primary-main hover:opacity-80 active:opacity-100 focus:opacity-80',
secondary:
'border bg-transparent border-darkBlue-100 text-darkBlue-100 hover:opacity-80 active:opacity-100 focus:opacity-80',
white:
'border bg-transparent border-white text-white hover:opacity-80 active:opacity-100 focus:opacity-80',
},
contained: {
default: 'bg-black hover:bg-gray-800 text-white',
primary: 'bg-blue-900 hover:bg-blue-800 text-white',
secondary: 'bg-blue-300 hover:bg-blue-500 text-black',
default:
'bg-primary-light text-white hover:opacity-80 active:opacity-100 focus:opacity-80',
primary:
'bg-primary-main text-white hover:opacity-80 active:opacity-100 focus:opacity-80',
secondary:
'bg-darkBlue-100 text-white hover:opacity-80 active:opacity-100 focus:opacity-80',
white:
'bg-white text-black hover:opacity-80 active:opacity-100 focus:opacity-80',
},
};
const sizeClasses = {
small: 'py-1 px-2 text-sm',
medium: 'py-2 px-4 text-base',
large: 'py-3 px-6 text-lg',
small: 'py-1 px-3 text-base',
medium: 'py-1 px-4 text-lg',
large: 'py-1 px-6 text-xl',
};
const fullWidthClasses = {
true: 'flex w-full',
false: 'inline-flex',
};
const Button = ({
@ -53,33 +77,52 @@ const Button = ({
variant = defaults.variant,
color = defaults.color,
size = defaults.size,
radius = defaults.radius,
rounded = defaults.rounded,
disabled = defaults.disabled,
type = defaults.type,
fullWidth = defaults.fullWidth,
startIcon: startIconProp,
endIcon: endIconProp,
className,
...rest
}) => {
const baseClasses =
'inline-flex items-center outline-none transition duration-300 ease-in-out font-bold focus:outline-none';
const startIcon = startIconProp && (
<div className="mr-2">{startIconProp}</div>
<div className="mr-2">
{React.cloneElement(startIconProp, {
className: classnames('w-4 h-4 fill-current'),
})}
</div>
);
const endIcon = endIconProp && <div className="ml-2">{endIconProp}</div>;
const endIcon = endIconProp && (
<div className="ml-2">
{React.cloneElement(endIconProp, {
className: classnames('w-4 h-4 fill-current'),
})}
</div>
);
const buttonElement = useRef(null);
const handleOnClick = e => {
buttonElement.current.blur();
if (rest.onClick) {
rest.onClick(e);
}
};
return (
<button
className={classnames(
baseClasses,
variantClasses[variant][color],
radiusClasses[radius],
roundedClasses[rounded],
sizeClasses[size],
fullWidthClasses[fullWidth],
disabledClasses[disabled],
className
)}
ref={buttonElement}
onClick={handleOnClick}
type={type}
{...rest}
>
@ -93,9 +136,10 @@ const Button = ({
Button.propTypes = {
children: PropTypes.node,
size: PropTypes.oneOf(['small', 'medium', 'large']),
radius: PropTypes.oneOf(['none', 'small', 'medium', 'large', 'full']),
rounded: PropTypes.oneOf(['none', 'small', 'medium', 'large', 'full']),
variant: PropTypes.oneOf(['text', 'outlined', 'contained']),
color: PropTypes.oneOf(['default', 'primary', 'secondary']),
color: PropTypes.oneOf(['default', 'primary', 'secondary', 'white']),
fullWidth: PropTypes.bool,
disabled: PropTypes.bool,
type: PropTypes.string,
startIcon: PropTypes.node,

View File

@ -15,22 +15,6 @@ Buttons are used to execute actions when users interacts with them.
<Props of={Button} />
## Contained Buttons
<Playground>
<>
<Button variant="contained" className="m-1">
Default
</Button>
<Button variant="contained" color="primary" className="m-1">
Primary
</Button>
<Button variant="contained" color="secondary" className="m-1">
Secondary
</Button>
</>
</Playground>
## Outlined Buttons
<Playground>
@ -44,9 +28,33 @@ Buttons are used to execute actions when users interacts with them.
<Button variant="outlined" color="secondary" className="m-1">
Secondary
</Button>
<Button variant="outlined" color="white" className="m-1">
White
</Button>
</>
</Playground>
## Contained Buttons
<Playground>
<>
<Button variant="contained" className="m-1">
Default
</Button>
<Button variant="contained" color="primary" className="m-1">
Primary
</Button>
<Button variant="contained" color="secondary" className="m-1">
Secondary
</Button>
<Button variant="contained" color="white" className="m-1">
White
</Button>
</>
</Playground>
## Text Buttons
<Playground>
@ -60,6 +68,159 @@ Buttons are used to execute actions when users interacts with them.
<Button variant="text" color="secondary" className="m-1">
Secondary
</Button>
<Button variant="text" color="white" className="m-1">
White
</Button>
</>
</Playground>
## Rounded Buttons
<Playground>
<>
<div className="mb-2">
<Button variant="contained" rounded="none" className="m-1">
Non Rounded
</Button>
<Button variant="contained" rounded="small" className="m-1">
Small Rounded
</Button>
<Button variant="contained" rounded="medium" className="m-1">
Medium Rounded
</Button>
<Button variant="contained" rounded="large" className="m-1">
Large Rounded
</Button>
<Button variant="contained" rounded="full" className="m-1">
Full Rounded
</Button>
</div>
<div className="mb-2">
<Button
variant="contained"
rounded="none"
color="primary"
className="m-1"
>
Non Rounded
</Button>
<Button
variant="contained"
rounded="small"
color="primary"
className="m-1"
>
Small Rounded
</Button>
<Button
variant="contained"
rounded="medium"
color="primary"
className="m-1"
>
Medium Rounded
</Button>
<Button
variant="contained"
rounded="large"
color="primary"
className="m-1"
>
Large Rounded
</Button>
<Button
variant="contained"
rounded="full"
color="primary"
className="m-1"
>
Full Rounded
</Button>
</div>
<div className="mb-2">
<Button
variant="contained"
rounded="none"
color="secondary"
className="m-1"
>
Non Rounded
</Button>
<Button
variant="contained"
rounded="small"
color="secondary"
className="m-1"
>
Small Rounded
</Button>
<Button
variant="contained"
rounded="medium"
color="secondary"
className="m-1"
>
Medium Rounded
</Button>
<Button
variant="contained"
rounded="large"
color="secondary"
className="m-1"
>
Large Rounded
</Button>
<Button
variant="contained"
rounded="full"
color="secondary"
className="m-1"
>
Full Rounded
</Button>
</div>
<div className="mb-2">
<Button
variant="contained"
rounded="none"
color="white"
className="m-1"
>
Non Rounded
</Button>
<Button
variant="contained"
rounded="small"
color="white"
className="m-1"
>
Small Rounded
</Button>
<Button
variant="contained"
rounded="medium"
color="white"
className="m-1"
>
Medium Rounded
</Button>
<Button
variant="contained"
rounded="large"
color="white"
className="m-1"
>
Large Rounded
</Button>
<Button
variant="contained"
rounded="full"
color="white"
className="m-1"
>
Full Rounded
</Button>
</div>
</>
</Playground>
@ -68,19 +229,19 @@ Buttons are used to execute actions when users interacts with them.
<Playground>
<>
<div>
<Button variant="text" size="small" className="m-1">
<Button variant="contained" size="small" className="m-1">
Small
</Button>
<Button variant="contained" size="medium" className="m-1">
Medium
</Button>
<Button variant="outlined" size="large" className="m-1">
<Button variant="contained" size="large" className="m-1">
Large
</Button>
</div>
<div>
<Button
variant="text"
variant="contained"
size="small"
color="primary"
className="m-1"
@ -96,39 +257,65 @@ Buttons are used to execute actions when users interacts with them.
Medium
</Button>
<Button
variant="outlined"
variant="contained"
size="large"
color="primary"
className="m-1"
>
large
Large
</Button>
</div>
<div>
<Button
variant="text"
size="small"
color="secondary"
className="m-1"
>
Small
</Button>
<Button
variant="contained"
size="medium"
color="secondary"
className="m-1"
>
Medium
</Button>
<Button
variant="outlined"
size="large"
color="secondary"
className="m-1"
>
Large
</Button>
<Button
variant="contained"
size="small"
color="secondary"
className="m-1"
>
Small
</Button>
<Button
variant="contained"
size="medium"
color="secondary"
className="m-1"
>
Medium
</Button>
<Button
variant="contained"
size="large"
color="secondary"
className="m-1"
>
Large
</Button>
</div>
<div>
<Button
variant="contained"
size="small"
color="white"
className="m-1"
>
Small
</Button>
<Button
variant="contained"
size="medium"
color="white"
className="m-1"
>
Medium
</Button>
<Button
variant="contained"
size="large"
color="white"
className="m-1"
>
Large
</Button>
</div>
</>
@ -147,7 +334,6 @@ Buttons are used to execute actions when users interacts with them.
className="m-1"
startIcon={
<svg
class="fill-current w-4 h-4"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
>
@ -163,12 +349,22 @@ Buttons are used to execute actions when users interacts with them.
className="m-1"
endIcon={
<svg
class="fill-current w-4 h-4"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
>
<path d="M13 8V2H7v6H2l8 8 8-8h-5zM0 18h20v2H0v-2z" />
</svg>
}
>
Download
</Button>
<Button
variant="outlined"
rounded="full"
color="default"
className="m-1"
endIcon={
<svg height="512pt" viewBox="0 0 512 512" width="512pt" xmlns="http://www.w3.org/2000/svg"><path d="m277.332031 128c0 11.78125-9.550781 21.332031-21.332031 21.332031s-21.332031-9.550781-21.332031-21.332031 9.550781-21.332031 21.332031-21.332031 21.332031 9.550781 21.332031 21.332031zm0 0"/><path d="m256 405.332031c-8.832031 0-16-7.167969-16-16v-165.332031h-21.332031c-8.832031 0-16-7.167969-16-16s7.167969-16 16-16h37.332031c8.832031 0 16 7.167969 16 16v181.332031c0 8.832031-7.167969 16-16 16zm0 0"/><path d="m256 512c-141.164062 0-256-114.835938-256-256s114.835938-256 256-256 256 114.835938 256 256-114.835938 256-256 256zm0-480c-123.519531 0-224 100.480469-224 224s100.480469 224 224 224 224-100.480469 224-224-100.480469-224-224-224zm0 0"/><path d="m304 405.332031h-96c-8.832031 0-16-7.167969-16-16s7.167969-16 16-16h96c8.832031 0 16 7.167969 16 16s-7.167969 16-16 16zm0 0"/></svg>
}
>
Download

View File

@ -153,7 +153,7 @@ module.exports = {
spacing: {
px: '1px',
'0': '0',
'1': '0.25rem',
'1': '0.15rem',
'2': '0.5rem',
'3': '0.75rem',
'4': '1rem',
@ -277,9 +277,9 @@ module.exports = {
],
},
fontSize: {
xs: '0.75rem',
sm: '0.875rem',
base: '1rem',
xs: '0.65rem',
sm: '0.75rem',
base: '0.875rem',
lg: '1.125rem',
xl: '1.25rem',
'2xl': '1.5rem',
@ -384,9 +384,25 @@ module.exports = {
},
opacity: {
'0': '0',
'25': '0.25',
'50': '0.5',
'75': '0.75',
'5': '.5',
'10': '.10',
'15': '.15',
'20': '.20',
'25': '.25',
'30': '.30',
'35': '.35',
'40': '.40',
'45': '.45',
'50': '.50',
'55': '.55',
'60': '.60',
'65': '.65',
'70': '.70',
'75': '.75',
'80': '.80',
'85': '.85',
'90': '.90',
'95': '.95',
'100': '1',
},
order: {
@ -642,15 +658,15 @@ module.exports = {
alignSelf: ['responsive'],
appearance: ['responsive'],
backgroundAttachment: ['responsive'],
backgroundColor: ['responsive', 'hover', 'focus'],
backgroundColor: ['responsive', 'hover', 'focus', 'active'],
backgroundPosition: ['responsive'],
backgroundRepeat: ['responsive'],
backgroundSize: ['responsive'],
borderCollapse: ['responsive'],
borderColor: ['responsive', 'hover', 'focus'],
borderRadius: ['responsive'],
borderStyle: ['responsive'],
borderWidth: ['responsive'],
borderColor: ['responsive', 'hover', 'focus', 'active'],
borderRadius: ['responsive', 'focus'],
borderStyle: ['responsive', 'focus'],
borderWidth: ['responsive', 'focus'],
boxShadow: ['responsive', 'hover', 'focus'],
boxSizing: ['responsive'],
cursor: ['responsive'],
@ -682,7 +698,7 @@ module.exports = {
minWidth: ['responsive'],
objectFit: ['responsive'],
objectPosition: ['responsive'],
opacity: ['responsive', 'hover', 'focus'],
opacity: ['responsive', 'hover', 'focus', 'active'],
order: ['responsive'],
outline: ['responsive', 'focus'],
overflow: ['responsive'],
@ -695,7 +711,7 @@ module.exports = {
strokeWidth: ['responsive'],
tableLayout: ['responsive'],
textAlign: ['responsive'],
textColor: ['responsive', 'hover', 'focus'],
textColor: ['responsive', 'hover', 'focus', 'active'],
textDecoration: ['responsive', 'hover', 'focus'],
textTransform: ['responsive'],
userSelect: ['responsive'],

View File

@ -4,4 +4,10 @@
[data-testid='live-preview'] {
padding: 10px;
background: #000;
}
[data-testid='main-container'] h2 {
margin: 20px 0;
font-weight: bold;
}