* tidy: UI updates to the borrow tables * feat: styled the toasts * tidy: format * fix: removed peer * fix: fixed the svgs * fix: stupid svgs * rename: X to Cross * tidy: wrap up the logic
206 lines
5.9 KiB
TypeScript
206 lines
5.9 KiB
TypeScript
import classNames from 'classnames'
|
|
import React, { LegacyRef, ReactElement, ReactNode } from 'react'
|
|
|
|
import { CircularProgress } from 'components/CircularProgress'
|
|
import { ChevronDown } from 'components/Icons'
|
|
import useStore from 'store'
|
|
|
|
interface Props {
|
|
children?: string | ReactNode
|
|
className?: string
|
|
color?: 'primary' | 'secondary' | 'tertiary' | 'quaternary'
|
|
disabled?: boolean
|
|
id?: string
|
|
showProgressIndicator?: boolean
|
|
size?: 'small' | 'medium' | 'large'
|
|
text?: string | ReactNode
|
|
variant?: 'solid' | 'transparent' | 'round'
|
|
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void
|
|
leftIcon?: ReactElement
|
|
rightIcon?: ReactElement
|
|
iconClassName?: string
|
|
hasSubmenu?: boolean
|
|
hasFocus?: boolean
|
|
}
|
|
|
|
export const buttonColorClasses = {
|
|
primary:
|
|
'font-bold gradient-primary-to-secondary hover:bg-white/20 active:bg-white/40 focus:bg-white/20',
|
|
secondary:
|
|
'border border-white/30 bg-transparent hover:bg-white/20 active:bg-white/40 focus:bg-white/20',
|
|
tertiary: 'bg-white/10 hover:bg-white/20 active:bg-white/40 focus:bg-white/20',
|
|
quaternary: 'bg-transparent text-white/60 hover:text-white ctive:text-white',
|
|
}
|
|
|
|
const focusClasses = {
|
|
primary: 'bg-white/20',
|
|
secondary: 'bg-white/20',
|
|
tertiary: 'bg-white/20',
|
|
quaternary: 'text-white',
|
|
}
|
|
|
|
const buttonBorderClasses =
|
|
'before:content-[" "] before:absolute before:inset-0 before:rounded-sm before:p-[1px] before:border-glas before:-z-1'
|
|
|
|
const buttonGradientClasses = [
|
|
'before:content-[" "] before:absolute before:inset-0 before:rounded-sm before:-z-1 before:opacity-0',
|
|
'before:gradient-secondary-to-primary before:transition-opacity before:ease-in',
|
|
'hover:before:opacity-100',
|
|
]
|
|
|
|
const buttonTransparentColorClasses = {
|
|
primary: 'hover:text-primary active:text-primary focus:text-primary',
|
|
secondary: 'hover:text-secondary active:text-secondary focus:text-secondary',
|
|
tertiary: 'hover:text-white/80 active:text-white/80 focus:text-white/80',
|
|
quaternary: 'text-white/60 hover:text-white active:text-white',
|
|
}
|
|
|
|
const buttonRoundSizeClasses = {
|
|
small: 'h-[32px] w-[32px]',
|
|
medium: 'h-[40px] w-[40px]',
|
|
large: 'h-[56px] w-[56px]',
|
|
}
|
|
|
|
export const buttonSizeClasses = {
|
|
small: 'text-sm',
|
|
medium: 'text-base',
|
|
large: 'text-lg',
|
|
}
|
|
|
|
export const buttonPaddingClasses = {
|
|
small: 'px-2.5 py-1.5 min-h-[32px]',
|
|
medium: 'px-3 py-2 min-h-[40px]',
|
|
large: 'px-3.5 py-2.5 min-h-[56px]',
|
|
}
|
|
|
|
export const buttonVariantClasses = {
|
|
solid: 'rounded-sm text-white shadow-button justify-center group',
|
|
transparent: 'rounded-sm bg-transparent p-0 transition duration-200 ease-in',
|
|
round: 'rounded-full p-0',
|
|
}
|
|
|
|
function glowElement(enableAnimations: boolean) {
|
|
return (
|
|
<svg
|
|
className={classNames(
|
|
enableAnimations && 'group-hover:animate-glow group-focus:animate-glow',
|
|
'glow-container z-1 opacity-0 ',
|
|
'pointer-events-none absolute inset-0 h-full w-full',
|
|
)}
|
|
>
|
|
<rect
|
|
pathLength='100'
|
|
strokeLinecap='round'
|
|
width='100%'
|
|
height='100%'
|
|
rx='4'
|
|
className='absolute glow-line group-hover:glow-hover group-focus:glow-hover'
|
|
/>
|
|
</svg>
|
|
)
|
|
}
|
|
|
|
export const Button = React.forwardRef(function Button(
|
|
{
|
|
children,
|
|
className = '',
|
|
color = 'primary',
|
|
disabled,
|
|
id = '',
|
|
showProgressIndicator,
|
|
size = 'small',
|
|
text,
|
|
variant = 'solid',
|
|
onClick,
|
|
leftIcon,
|
|
rightIcon,
|
|
iconClassName,
|
|
hasSubmenu,
|
|
hasFocus,
|
|
}: Props,
|
|
ref,
|
|
) {
|
|
const buttonClasses = []
|
|
const enableAnimations = useStore((s) => s.enableAnimations)
|
|
const isDisabled = disabled || showProgressIndicator
|
|
|
|
switch (variant) {
|
|
case 'round':
|
|
buttonClasses.push(
|
|
buttonSizeClasses[size],
|
|
buttonRoundSizeClasses[size],
|
|
buttonPaddingClasses[size],
|
|
buttonColorClasses[color],
|
|
)
|
|
break
|
|
|
|
case 'transparent':
|
|
buttonClasses.push(buttonSizeClasses[size], buttonTransparentColorClasses[color])
|
|
break
|
|
|
|
case 'solid':
|
|
buttonClasses.push(
|
|
buttonSizeClasses[size],
|
|
buttonPaddingClasses[size],
|
|
buttonColorClasses[color],
|
|
)
|
|
break
|
|
default:
|
|
}
|
|
|
|
return (
|
|
<button
|
|
className={classNames(
|
|
'relative z-1 flex items-center',
|
|
'cursor-pointer appearance-none break-normal outline-none',
|
|
'text-white transition-all',
|
|
enableAnimations && 'transition-color',
|
|
buttonClasses,
|
|
buttonVariantClasses[variant],
|
|
variant === 'solid' && color === 'tertiary' && buttonBorderClasses,
|
|
variant === 'solid' && color === 'primary' && buttonGradientClasses,
|
|
disabled && 'pointer-events-none opacity-50',
|
|
hasFocus && focusClasses[color],
|
|
className,
|
|
)}
|
|
id={id}
|
|
ref={ref as LegacyRef<HTMLButtonElement>}
|
|
onClick={disabled ? () => {} : onClick}
|
|
>
|
|
{leftIcon && !showProgressIndicator && (
|
|
<span
|
|
className={classNames(
|
|
'flex items-center justify-center',
|
|
(text || children) && 'mr-2',
|
|
iconClassName ?? 'h-4 w-4',
|
|
)}
|
|
>
|
|
{leftIcon}
|
|
</span>
|
|
)}
|
|
{text && !children && !showProgressIndicator && <span>{text}</span>}
|
|
{children && !showProgressIndicator && children}
|
|
{rightIcon && !showProgressIndicator && (
|
|
<span
|
|
className={classNames(
|
|
'flex items-center justify-center',
|
|
(text || children) && 'ml-2',
|
|
iconClassName ?? 'h-4 w-4',
|
|
)}
|
|
>
|
|
{rightIcon}
|
|
</span>
|
|
)}
|
|
{hasSubmenu && !showProgressIndicator && (
|
|
<span className='ml-2 inline-block w-2.5'>
|
|
<ChevronDown />
|
|
</span>
|
|
)}
|
|
{variant === 'solid' && !isDisabled && glowElement(enableAnimations)}
|
|
{showProgressIndicator && (
|
|
<CircularProgress size={size === 'small' ? 10 : size === 'medium' ? 12 : 18} />
|
|
)}
|
|
</button>
|
|
)
|
|
})
|