Path: blob/1.0-develop/resources/scripts/components/elements/Button.tsx
7461 views
import React from 'react';1import styled, { css } from 'styled-components/macro';2import tw from 'twin.macro';3import Spinner from '@/components/elements/Spinner';45interface Props {6isLoading?: boolean;7size?: 'xsmall' | 'small' | 'large' | 'xlarge';8color?: 'green' | 'red' | 'primary' | 'grey';9isSecondary?: boolean;10}1112const ButtonStyle = styled.button<Omit<Props, 'isLoading'>>`13${tw`relative inline-block rounded p-2 uppercase tracking-wide text-sm transition-all duration-150 border`};1415${(props) =>16((!props.isSecondary && !props.color) || props.color === 'primary') &&17css<Props>`18${(props) => !props.isSecondary && tw`bg-primary-500 border-primary-600 border text-primary-50`};1920&:hover:not(:disabled) {21${tw`bg-primary-600 border-primary-700`};22}23`};2425${(props) =>26props.color === 'grey' &&27css`28${tw`border-neutral-600 bg-neutral-500 text-neutral-50`};2930&:hover:not(:disabled) {31${tw`bg-neutral-600 border-neutral-700`};32}33`};3435${(props) =>36props.color === 'green' &&37css<Props>`38${tw`border-green-600 bg-green-500 text-green-50`};3940&:hover:not(:disabled) {41${tw`bg-green-600 border-green-700`};42}4344${(props) =>45props.isSecondary &&46css`47&:active:not(:disabled) {48${tw`bg-green-600 border-green-700`};49}50`};51`};5253${(props) =>54props.color === 'red' &&55css<Props>`56${tw`border-red-600 bg-red-500 text-red-50`};5758&:hover:not(:disabled) {59${tw`bg-red-600 border-red-700`};60}6162${(props) =>63props.isSecondary &&64css`65&:active:not(:disabled) {66${tw`bg-red-600 border-red-700`};67}68`};69`};7071${(props) => props.size === 'xsmall' && tw`px-2 py-1 text-xs`};72${(props) => (!props.size || props.size === 'small') && tw`px-4 py-2`};73${(props) => props.size === 'large' && tw`p-4 text-sm`};74${(props) => props.size === 'xlarge' && tw`p-4 w-full`};7576${(props) =>77props.isSecondary &&78css<Props>`79${tw`border-neutral-600 bg-transparent text-neutral-200`};8081&:hover:not(:disabled) {82${tw`border-neutral-500 text-neutral-100`};83${(props) => props.color === 'red' && tw`bg-red-500 border-red-600 text-red-50`};84${(props) => props.color === 'primary' && tw`bg-primary-500 border-primary-600 text-primary-50`};85${(props) => props.color === 'green' && tw`bg-green-500 border-green-600 text-green-50`};86}87`};8889&:disabled {90opacity: 0.55;91cursor: default;92}93`;9495type ComponentProps = Omit<JSX.IntrinsicElements['button'], 'ref' | keyof Props> & Props;9697const Button: React.FC<ComponentProps> = ({ children, isLoading, ...props }) => (98<ButtonStyle {...props}>99{isLoading && (100<div css={tw`flex absolute justify-center items-center w-full h-full left-0 top-0`}>101<Spinner size={'small'} />102</div>103)}104<span css={isLoading ? tw`text-transparent` : undefined}>{children}</span>105</ButtonStyle>106);107108type LinkProps = Omit<JSX.IntrinsicElements['a'], 'ref' | keyof Props> & Props;109110const LinkButton: React.FC<LinkProps> = (props) => <ButtonStyle as={'a'} {...props} />;111112export { LinkButton, ButtonStyle };113export default Button;114115116