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

View File

@ -15,22 +15,6 @@ Buttons are used to execute actions when users interacts with them.
<Props of={Button} /> <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 ## Outlined Buttons
<Playground> <Playground>
@ -44,9 +28,33 @@ Buttons are used to execute actions when users interacts with them.
<Button variant="outlined" color="secondary" className="m-1"> <Button variant="outlined" color="secondary" className="m-1">
Secondary Secondary
</Button> </Button>
<Button variant="outlined" color="white" className="m-1">
White
</Button>
</> </>
</Playground> </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 ## Text Buttons
<Playground> <Playground>
@ -60,6 +68,159 @@ Buttons are used to execute actions when users interacts with them.
<Button variant="text" color="secondary" className="m-1"> <Button variant="text" color="secondary" className="m-1">
Secondary Secondary
</Button> </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> </Playground>
@ -68,19 +229,19 @@ Buttons are used to execute actions when users interacts with them.
<Playground> <Playground>
<> <>
<div> <div>
<Button variant="text" size="small" className="m-1"> <Button variant="contained" size="small" className="m-1">
Small Small
</Button> </Button>
<Button variant="contained" size="medium" className="m-1"> <Button variant="contained" size="medium" className="m-1">
Medium Medium
</Button> </Button>
<Button variant="outlined" size="large" className="m-1"> <Button variant="contained" size="large" className="m-1">
Large Large
</Button> </Button>
</div> </div>
<div> <div>
<Button <Button
variant="text" variant="contained"
size="small" size="small"
color="primary" color="primary"
className="m-1" className="m-1"
@ -96,39 +257,65 @@ Buttons are used to execute actions when users interacts with them.
Medium Medium
</Button> </Button>
<Button <Button
variant="outlined" variant="contained"
size="large" size="large"
color="primary" color="primary"
className="m-1" className="m-1"
> >
large Large
</Button> </Button>
</div> </div>
<div> <div>
<Button <Button
variant="text" variant="contained"
size="small" size="small"
color="secondary" color="secondary"
className="m-1" className="m-1"
> >
Small Small
</Button> </Button>
<Button <Button
variant="contained" variant="contained"
size="medium" size="medium"
color="secondary" color="secondary"
className="m-1" className="m-1"
> >
Medium Medium
</Button> </Button>
<Button <Button
variant="outlined" variant="contained"
size="large" size="large"
color="secondary" color="secondary"
className="m-1" className="m-1"
> >
Large Large
</Button> </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> </div>
</> </>
@ -147,7 +334,6 @@ Buttons are used to execute actions when users interacts with them.
className="m-1" className="m-1"
startIcon={ startIcon={
<svg <svg
class="fill-current w-4 h-4"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20" viewBox="0 0 20 20"
> >
@ -163,12 +349,22 @@ Buttons are used to execute actions when users interacts with them.
className="m-1" className="m-1"
endIcon={ endIcon={
<svg <svg
class="fill-current w-4 h-4"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20" viewBox="0 0 20 20"
> >
<path d="M13 8V2H7v6H2l8 8 8-8h-5zM0 18h20v2H0v-2z" /> <path d="M13 8V2H7v6H2l8 8 8-8h-5zM0 18h20v2H0v-2z" />
</svg> </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 Download

View File

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

View File

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