240 lines
6.9 KiB
Plaintext
240 lines
6.9 KiB
Plaintext
import classNames from 'classnames';
|
|
import {
|
|
StyleColorVariants,
|
|
StyleColorVariantsMap,
|
|
StyleType,
|
|
} from 'core/_variants';
|
|
import React from 'react';
|
|
|
|
type Props = {
|
|
href?: string;
|
|
variant?: StyleColorVariants;
|
|
type?: StyleType;
|
|
iconed?: boolean | "only";
|
|
glowing?: boolean;
|
|
disabled?: boolean;
|
|
onClick?: (event: React.MouseEvent) => void;
|
|
children?: React.ReactNode;
|
|
className?: string | undefined;
|
|
rel?: string | undefined;
|
|
htmlType?: 'button' | 'submit' | 'reset' | undefined;
|
|
};
|
|
|
|
const buttonBgVariants: StyleColorVariantsMap<string> = {
|
|
gray: 'bg-gray-500',
|
|
blue: 'bg-blue-500',
|
|
emerald: 'bg-emerald-600',
|
|
pink: 'bg-pink-500',
|
|
purple: 'bg-purple-500',
|
|
red: 'bg-red-500',
|
|
sky: 'bg-sky-500',
|
|
yellow: 'bg-yellow-500',
|
|
"dark-coral": "bg-dark-coral-500",
|
|
};
|
|
|
|
const buttonBgDisabledVariants: StyleColorVariantsMap<string> = {
|
|
gray: 'bg-gray-200',
|
|
blue: 'bg-blue-100/10',
|
|
emerald: 'bg-emerald-200/50',
|
|
pink: 'bg-pink-200/50',
|
|
purple: 'bg-purple-200/50',
|
|
red: 'bg-red-200/50',
|
|
sky: 'bg-sky-200/50',
|
|
yellow: 'bg-yellow-200/50',
|
|
"dark-coral": "bg-dark-coral-200/50",
|
|
};
|
|
|
|
const buttonBgDisabledHoverVariants: StyleColorVariantsMap<string> = {
|
|
gray: 'hover:bg-gray-500/50',
|
|
blue: 'hover:bg-blue-100/10',
|
|
emerald: 'hover:bg-emerald-500/50',
|
|
pink: 'hover:bg-pink-500/50',
|
|
purple: 'hover:bg-purple-500/50',
|
|
red: 'hover:bg-red-500/50',
|
|
sky: 'hover:bg-sky-500/50',
|
|
yellow: 'hover:bg-yellow-500/50',
|
|
"dark-coral": "hover:bg-dark-coral-500/50",
|
|
};
|
|
|
|
const buttonHoverBgVariants: StyleColorVariantsMap<string> = {
|
|
gray: 'hover:bg-gray-600',
|
|
blue: 'hover:bg-blue-400',
|
|
emerald: 'hover:bg-emerald-600',
|
|
pink: 'hover:bg-pink-600',
|
|
purple: 'hover:bg-purple-600',
|
|
red: 'hover:bg-red-600',
|
|
sky: 'hover:bg-sky-600',
|
|
yellow: 'hover:bg-yellow-600',
|
|
"dark-coral": "hover:bg-dark-coral-600",
|
|
};
|
|
|
|
const buttonBorderVariants: StyleColorVariantsMap<string> = {
|
|
gray: 'border-gray-500',
|
|
blue: 'border-blue-500',
|
|
emerald: 'border-emerald-700',
|
|
pink: 'border-pink-300',
|
|
purple: 'border-purple-300',
|
|
red: 'border-red-300',
|
|
sky: 'border-sky-300',
|
|
yellow: 'border-yellow-300',
|
|
"dark-coral": "border-dark-coral-500",
|
|
};
|
|
|
|
const buttonBorderHoverVariants: StyleColorVariantsMap<string> = {
|
|
gray: 'hover:border-gray-500',
|
|
blue: 'hover:border-blue-400',
|
|
emerald: 'hover:border-emerald-900',
|
|
pink: 'hover:border-pink-400',
|
|
purple: 'hover:border-purple-400',
|
|
red: 'hover:border-red-500',
|
|
sky: 'hover:border-sky-400',
|
|
yellow: 'hover:border-yellow-400',
|
|
"dark-coral": "hover:border-dark-coral-400",
|
|
};
|
|
|
|
const buttonTextVariants: StyleColorVariantsMap<string> = {
|
|
gray: 'text-white',
|
|
blue: 'text-white',
|
|
emerald: 'text-emerald-300',
|
|
pink: 'text-white',
|
|
purple: 'text-white',
|
|
red: 'text-white',
|
|
sky: 'text-white',
|
|
yellow: 'text-white',
|
|
"dark-coral": "text-white",
|
|
};
|
|
|
|
const buttonTextHoverVariants: StyleColorVariantsMap<string> = {
|
|
blue: 'hover:text-white',
|
|
emerald: 'hover:text-emerald-900',
|
|
gray: 'hover:text-white',
|
|
pink: 'hover:text-white',
|
|
purple: 'hover:text-white',
|
|
red: 'hover:text-white',
|
|
sky: 'hover:text-white',
|
|
yellow: 'hover:text-white',
|
|
"dark-coral": 'hover:text-white',
|
|
}
|
|
|
|
const buttonTextMutedVariants: StyleColorVariantsMap<string> = {
|
|
gray: 'text-gray-500',
|
|
blue: 'text-gray-50',
|
|
emerald: 'text-gray-50',
|
|
pink: 'text-gray-50',
|
|
purple: 'text-gray-50',
|
|
red: 'text-gray-50',
|
|
sky: 'text-gray-50',
|
|
yellow: 'text-gray-50',
|
|
"dark-coral": "text-gray-500",
|
|
};
|
|
|
|
const buttonGlowVariants: StyleColorVariantsMap<string> = {
|
|
gray: 'shadow-gray-300/50',
|
|
blue: 'shadow-blue-500/50',
|
|
emerald: 'shadow-blue-700/50',
|
|
pink: 'shadow-blue-300/50',
|
|
purple: 'shadow-blue-300/50',
|
|
red: 'shadow-blue-300/50',
|
|
sky: 'shadow-blue-300/50',
|
|
yellow: 'shadow-blue-300/50',
|
|
"dark-coral": "shadow-dark-coral-300/50",
|
|
};
|
|
|
|
const buttonHoverGlowVariants: StyleColorVariantsMap<string> = {
|
|
gray: 'hover:shadow-gray-300/50',
|
|
blue: 'hover:shadow-blue-400/50',
|
|
emerald: 'hover:shadow-blue-300/50',
|
|
pink: 'hover:shadow-blue-300/50',
|
|
purple: 'hover:shadow-blue-300/50',
|
|
red: 'hover:shadow-blue-300/50',
|
|
sky: 'hover:shadow-blue-300/50',
|
|
yellow: 'hover:shadow-blue-300/50',
|
|
"dark-coral": "hover:shadow-dark-coral-300/50",
|
|
};
|
|
|
|
const isURL = (str: string) =>
|
|
/^(?:\w+:)?\/\/([^\s.]+\.\S{2}|localhost[:?\d]*)\S*$/.test(str);
|
|
|
|
const isInternalURL = (str: string) => /^\/(\S*\/)*\S*\/?$/.test(str);
|
|
|
|
/**
|
|
* Common button component
|
|
* @param {string|undefined} href New location link
|
|
* @param {boolean} iconed Flag to process component with icon. Default: `false`
|
|
* @param {StyleGlobalVariants|undefined} variant Button variant.
|
|
* Default: `base`
|
|
* @param {StyleType} type Button type.
|
|
* Default: `fill`
|
|
* @param {boolean|undefined} glowing Enables glowing shadow around
|
|
* button element. Default `false`
|
|
* @param {boolean|undefined} disabled Shows button element as
|
|
* disabled item
|
|
* @return {JSX.Element}
|
|
*/
|
|
const Button = ({
|
|
href,
|
|
iconed,
|
|
variant = 'gray',
|
|
type = 'fill',
|
|
glowing = false,
|
|
disabled,
|
|
onClick: onPress,
|
|
children,
|
|
className,
|
|
rel,
|
|
htmlType,
|
|
}: Props) =>{
|
|
const isExternal = isURL(href ?? '');
|
|
const isInternal = isInternalURL(href ?? '');
|
|
|
|
const As = isExternal || isInternal ? 'a' : 'button';
|
|
|
|
return (
|
|
<As
|
|
rel={rel}
|
|
href={href}
|
|
type={htmlType}
|
|
onClick={!disabled ? onPress : undefined}
|
|
className={classNames([
|
|
'text-center',
|
|
'rounded-lg font-semibold',
|
|
'transition-[box-shadow,background-color,color,border-color]',
|
|
'border',
|
|
{
|
|
'px-2 py-2': iconed === "only",
|
|
'py-3 pl-2 pr-5': iconed && iconed !== "only",
|
|
'py-3 px-8': !iconed,
|
|
'!cursor-default': disabled,
|
|
},
|
|
{
|
|
'shadow-lg': !disabled && glowing && type !== 'text',
|
|
'hover:shadow-lg': !disabled && glowing,
|
|
// Text variants
|
|
[`${buttonTextVariants[variant]}`]: !disabled,
|
|
[`${buttonTextHoverVariants[variant]}`]: !disabled && type === "outline",
|
|
// Background variants
|
|
[`${buttonBgVariants[variant]}`]: !disabled && type === 'fill',
|
|
[`${buttonHoverBgVariants[variant]}`]: !disabled,
|
|
// Glowing variants
|
|
[`${buttonGlowVariants[variant]}`]:
|
|
!disabled && glowing === true && type !== 'text',
|
|
[`${buttonHoverGlowVariants[variant]}`]: glowing,
|
|
// Disabled variants
|
|
[`${buttonTextMutedVariants[variant]}`]: disabled,
|
|
[`${buttonBgDisabledVariants[variant]}`]: disabled && type === 'fill',
|
|
[`${buttonBgDisabledHoverVariants[variant]}`]: disabled,
|
|
// Border variants
|
|
[`${buttonBorderVariants[variant]}`]: type !== 'text',
|
|
'!border-transparent': disabled || type === 'text',
|
|
},
|
|
buttonBorderHoverVariants[variant],
|
|
className,
|
|
])}
|
|
>
|
|
{children}
|
|
</As>
|
|
);
|
|
};
|
|
|
|
export default Button;
|