Instantly share code, notes, and snippets.
Created
October 15, 2021 09:15
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save mtt87/43d7d92974064b50b840a5a20b770840 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Box from '@components/ui/Box' | |
import Flex from '@components/ui/Flex' | |
import Spinner from '@components/ui/Spinner' | |
import { styled, theme } from '@src/stitches.config' | |
import * as React from 'react' | |
const StyledButton = styled('button', { | |
fontFamily: '$inter', | |
fontWeight: '$700', | |
borderRadius: '$4', | |
lineHeight: 1.5, | |
display: 'flex', | |
alignItems: 'center', | |
justifyContent: 'center', | |
position: 'relative', | |
cursor: 'pointer', | |
variants: { | |
variant: { | |
solid: { | |
color: 'white', | |
backgroundColor: theme.colors.blue500, | |
'&:hover': { | |
backgroundColor: theme.colors.blue400, | |
}, | |
'&:active': { | |
backgroundColor: theme.colors.blue600, | |
}, | |
'&:disabled': { | |
backgroundColor: theme.colors.grey500, | |
cursor: 'not-allowed', | |
}, | |
}, | |
outline: { | |
color: theme.colors.blue500, | |
backgroundColor: 'white', | |
boxShadow: `inset 0px 0px 0px 1px ${theme.colors.blue500}`, | |
'&:hover': { | |
backgroundColor: theme.colors.blue100, | |
}, | |
'&:active': { | |
backgroundColor: theme.colors.blue200, | |
}, | |
'&:disabled': { | |
backgroundColor: 'white', | |
boxShadow: `inset 0px 0px 0px 1px ${theme.colors.grey500}`, | |
color: theme.colors.grey500, | |
cursor: 'not-allowed', | |
}, | |
}, | |
link: { | |
color: theme.colors.blue500, | |
fontWeight: '$400', | |
}, | |
}, | |
size: { | |
small: { | |
fontSize: '$1', | |
paddingTop: 4, | |
paddingBottom: 4, | |
paddingLeft: 10, | |
paddingRight: 10, | |
borderRadius: '$2', | |
}, | |
medium: { | |
fontSize: '$2', | |
paddingTop: '$1', | |
paddingBottom: '$1', | |
paddingLeft: '$2', | |
paddingRight: '$2', | |
}, | |
large: { | |
fontSize: '$3', | |
paddingTop: '12px', | |
paddingBottom: '12px', | |
paddingLeft: '$3', | |
paddingRight: '$3', | |
}, | |
}, | |
color: { | |
red: {}, | |
blue: {}, | |
}, | |
}, | |
defaultVariants: { | |
variant: 'solid', | |
size: 'medium', | |
color: 'blue', | |
}, | |
compoundVariants: [ | |
{ | |
variant: 'link', | |
css: { | |
paddingTop: 0, | |
paddingBottom: 0, | |
paddingLeft: 0, | |
paddingRight: 0, | |
}, | |
}, | |
{ | |
color: 'red', | |
variant: 'solid', | |
css: { | |
backgroundColor: theme.colors.red500, | |
'&:hover': { | |
backgroundColor: theme.colors.red400, | |
}, | |
'&:active': { | |
backgroundColor: theme.colors.red600, | |
}, | |
'&:disabled': { | |
backgroundColor: theme.colors.grey500, | |
cursor: 'not-allowed', | |
}, | |
}, | |
}, | |
{ | |
color: 'red', | |
variant: 'outline', | |
css: { | |
color: theme.colors.red500, | |
boxShadow: `inset 0px 0px 0px 1px ${theme.colors.red500}`, | |
'&:hover': { | |
backgroundColor: theme.colors.red100, | |
}, | |
'&:active': { | |
backgroundColor: theme.colors.red200, | |
}, | |
'&:disabled': { | |
boxShadow: `inset 0px 0px 0px 1px ${theme.colors.grey500}`, | |
backgroundColor: 'white', | |
cursor: 'not-allowed', | |
}, | |
}, | |
}, | |
], | |
}) | |
export type ButtonProps = React.ComponentProps<typeof StyledButton> & { | |
as?: keyof JSX.IntrinsicElements | |
loading?: boolean | |
} | |
const Button: React.FC<ButtonProps> = React.forwardRef( | |
( | |
{ | |
children, | |
loading = false, | |
size, | |
onClick, | |
...remainingProps | |
}: ButtonProps, | |
ref, | |
) => ( | |
<StyledButton | |
onClick={loading ? undefined : onClick} | |
{...remainingProps} | |
size={size} | |
ref={ref} | |
> | |
<Flex | |
css={{ | |
visibility: loading ? 'hidden' : 'visible', | |
alignItems: 'center', | |
justifyContent: 'center', | |
}} | |
> | |
{children} | |
</Flex> | |
{loading ? ( | |
<Box | |
css={{ | |
position: 'absolute', | |
width: size === 'large' ? '40px' : '24px', | |
height: size === 'large' ? '40px' : '24px', | |
}} | |
> | |
<Spinner size={size === 'large' ? 'medium' : 'small'} color="light" /> | |
</Box> | |
) : null} | |
</StyledButton> | |
), | |
) | |
Button.displayName = 'Button' | |
export default Button |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment