Skip to content

Instantly share code, notes, and snippets.

@mtt87
Created October 15, 2021 09:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mtt87/43d7d92974064b50b840a5a20b770840 to your computer and use it in GitHub Desktop.
Save mtt87/43d7d92974064b50b840a5a20b770840 to your computer and use it in GitHub Desktop.
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