2022-03-07 13:27:17 +00:00
|
|
|
import { AnchorHTMLAttributes, ButtonHTMLAttributes, forwardRef } from 'react';
|
2022-03-01 09:26:26 +00:00
|
|
|
import classNames from 'classnames';
|
2022-03-02 09:56:05 +00:00
|
|
|
import { Icon, IconName } from '../icon';
|
2022-03-08 14:03:50 +00:00
|
|
|
import {
|
2022-03-09 13:05:42 +00:00
|
|
|
includesLeftPadding,
|
|
|
|
includesRightPadding,
|
|
|
|
includesBorderWidth,
|
2022-03-08 14:03:50 +00:00
|
|
|
} from '../../utils/class-names';
|
2022-03-07 12:27:56 +00:00
|
|
|
|
|
|
|
interface CommonProps {
|
2022-03-01 09:26:26 +00:00
|
|
|
children?: React.ReactNode;
|
|
|
|
variant?: 'primary' | 'secondary' | 'accent' | 'inline';
|
|
|
|
className?: string;
|
2022-03-02 09:56:05 +00:00
|
|
|
prependIconName?: IconName;
|
|
|
|
appendIconName?: IconName;
|
2022-03-01 09:26:26 +00:00
|
|
|
}
|
2022-03-07 12:27:56 +00:00
|
|
|
export interface ButtonProps
|
|
|
|
extends ButtonHTMLAttributes<HTMLButtonElement>,
|
|
|
|
CommonProps {}
|
|
|
|
|
|
|
|
export interface AnchorButtonProps
|
|
|
|
extends AnchorHTMLAttributes<HTMLAnchorElement>,
|
|
|
|
CommonProps {}
|
2022-03-01 09:26:26 +00:00
|
|
|
|
2022-03-07 12:27:56 +00:00
|
|
|
const getClassName = (
|
|
|
|
className: CommonProps['className'],
|
|
|
|
variant: CommonProps['variant']
|
2022-03-07 21:16:06 +00:00
|
|
|
) => {
|
2022-03-09 13:05:42 +00:00
|
|
|
const paddingLeftProvided = includesLeftPadding(className);
|
|
|
|
const paddingRightProvided = includesRightPadding(className);
|
|
|
|
const borderWidthProvided = includesBorderWidth(className);
|
2022-03-07 21:16:06 +00:00
|
|
|
return classNames(
|
2022-03-01 09:26:26 +00:00
|
|
|
[
|
|
|
|
'inline-flex',
|
|
|
|
'items-center',
|
2022-03-03 11:11:36 +00:00
|
|
|
'justify-center',
|
2022-03-01 09:26:26 +00:00
|
|
|
'box-border',
|
|
|
|
'h-28',
|
|
|
|
'text-ui',
|
|
|
|
'no-underline',
|
|
|
|
'hover:underline',
|
|
|
|
'disabled:no-underline',
|
2022-03-03 14:48:40 +00:00
|
|
|
'transition-all',
|
2022-03-01 09:26:26 +00:00
|
|
|
],
|
|
|
|
{
|
2022-03-09 13:05:42 +00:00
|
|
|
'pl-28': !(paddingLeftProvided || variant === 'inline'),
|
|
|
|
'pr-28': !(paddingRightProvided || variant === 'inline'),
|
|
|
|
|
|
|
|
border: !borderWidthProvided,
|
2022-03-03 11:11:36 +00:00
|
|
|
|
2022-03-03 14:48:40 +00:00
|
|
|
'hover:border-black dark:hover:border-white': variant !== 'inline',
|
|
|
|
'active:border-black dark:active:border-white': true,
|
2022-03-01 09:26:26 +00:00
|
|
|
|
2022-03-03 14:48:40 +00:00
|
|
|
'bg-black dark:bg-white': variant === 'primary',
|
2022-03-07 13:27:17 +00:00
|
|
|
'border-black-60 dark:border-white-60':
|
2022-03-03 14:48:40 +00:00
|
|
|
variant === 'primary' || variant === 'secondary',
|
|
|
|
'text-white dark:text-black': variant === 'primary',
|
2022-03-07 13:27:17 +00:00
|
|
|
'hover:bg-black-80 dark:hover:bg-white-80': variant === 'primary',
|
2022-03-03 14:48:40 +00:00
|
|
|
'active:bg-white dark:active:bg-black':
|
|
|
|
variant === 'primary' || variant === 'accent',
|
|
|
|
'active:text-black dark:active:text-white':
|
|
|
|
variant === 'primary' || variant === 'accent',
|
|
|
|
|
|
|
|
'bg-white dark:bg-black': variant === 'secondary',
|
|
|
|
'text-black dark:text-white': variant === 'secondary',
|
2022-03-07 13:27:17 +00:00
|
|
|
'hover:bg-black-25 dark:hover:bg-white-25': variant === 'secondary',
|
2022-03-03 14:48:40 +00:00
|
|
|
'hover:text-black dark:hover:text-white':
|
2022-03-01 09:26:26 +00:00
|
|
|
variant === 'secondary' || variant === 'accent',
|
2022-03-03 14:48:40 +00:00
|
|
|
'active:bg-black dark:active:bg-white': variant === 'secondary',
|
|
|
|
'active:text-white dark:active:text-black': variant === 'secondary',
|
2022-03-01 09:26:26 +00:00
|
|
|
|
|
|
|
uppercase: variant === 'accent',
|
2022-03-03 14:48:40 +00:00
|
|
|
'bg-vega-yellow dark:bg-vega-yellow': variant === 'accent',
|
|
|
|
'border-transparent dark:border-transparent':
|
|
|
|
variant === 'accent' || variant === 'inline',
|
2022-03-04 16:21:24 +00:00
|
|
|
'hover:bg-vega-yellow-dark dark:hover:bg-vega-yellow/30':
|
2022-03-03 14:48:40 +00:00
|
|
|
variant === 'accent',
|
2022-03-09 13:05:42 +00:00
|
|
|
'text-black dark:text-black': variant === 'accent',
|
2022-03-04 16:21:24 +00:00
|
|
|
'hover:text-white dark:hover:text-white': variant === 'accent',
|
2022-03-01 09:26:26 +00:00
|
|
|
|
2022-03-09 13:05:42 +00:00
|
|
|
'pl-4': variant === 'inline' && !paddingLeftProvided,
|
|
|
|
'pr-4': variant === 'inline' && !paddingRightProvided,
|
|
|
|
'border-0': variant === 'inline' && !borderWidthProvided,
|
2022-03-01 09:26:26 +00:00
|
|
|
underline: variant === 'inline',
|
|
|
|
'hover:no-underline': variant === 'inline',
|
2022-03-04 16:21:24 +00:00
|
|
|
'hover:border-transparent dark:hover:border-transparent':
|
2022-03-03 14:48:40 +00:00
|
|
|
variant === 'inline',
|
2022-03-04 16:21:24 +00:00
|
|
|
'active:border-transparent dark:active:border-transparent':
|
|
|
|
variant === 'inline',
|
|
|
|
'active:text-black dark:active:text-vega-yellow': variant === 'inline',
|
2022-03-07 13:27:17 +00:00
|
|
|
'text-black-95 dark:text-white-95': variant === 'inline',
|
2022-03-03 14:48:40 +00:00
|
|
|
'hover:text-black hover:dark:text-white': variant === 'inline',
|
|
|
|
|
2022-03-07 13:27:17 +00:00
|
|
|
'disabled:bg-black-10 dark:disabled:bg-white-10': variant !== 'inline',
|
|
|
|
'disabled:text-black-60 dark:disabled:text-white-60':
|
2022-03-03 14:48:40 +00:00
|
|
|
variant !== 'inline',
|
2022-03-07 13:27:17 +00:00
|
|
|
'disabled:border-black-25 dark:disabled:border-white-25':
|
2022-03-03 14:48:40 +00:00
|
|
|
variant !== 'inline',
|
2022-03-01 09:26:26 +00:00
|
|
|
},
|
|
|
|
className
|
|
|
|
);
|
2022-03-07 21:16:06 +00:00
|
|
|
};
|
2022-03-07 12:27:56 +00:00
|
|
|
|
|
|
|
const getContent = (
|
|
|
|
children: React.ReactNode,
|
|
|
|
prependIconName?: IconName,
|
|
|
|
appendIconName?: IconName
|
|
|
|
) => {
|
2022-03-02 09:56:05 +00:00
|
|
|
const iconName = prependIconName || appendIconName;
|
2022-03-07 12:27:56 +00:00
|
|
|
if (iconName === undefined) {
|
|
|
|
return children;
|
2022-03-02 09:56:05 +00:00
|
|
|
}
|
2022-03-07 12:27:56 +00:00
|
|
|
const iconClassName = classNames(['fill-current'], {
|
|
|
|
'mr-8': prependIconName,
|
|
|
|
'ml-8': appendIconName,
|
|
|
|
});
|
|
|
|
const icon = <Icon name={iconName} className={iconClassName} size={16} />;
|
2022-03-01 09:26:26 +00:00
|
|
|
return (
|
2022-03-07 12:27:56 +00:00
|
|
|
<>
|
2022-03-02 09:56:05 +00:00
|
|
|
{prependIconName && icon}
|
2022-03-01 09:26:26 +00:00
|
|
|
{children}
|
2022-03-02 09:56:05 +00:00
|
|
|
{appendIconName && icon}
|
2022-03-07 12:27:56 +00:00
|
|
|
</>
|
2022-03-01 09:26:26 +00:00
|
|
|
);
|
2022-03-07 12:27:56 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
|
|
(
|
|
|
|
{
|
|
|
|
variant = 'primary',
|
|
|
|
children,
|
|
|
|
className,
|
|
|
|
prependIconName,
|
|
|
|
appendIconName,
|
2022-03-07 20:45:39 +00:00
|
|
|
...props
|
2022-03-07 12:27:56 +00:00
|
|
|
},
|
|
|
|
ref
|
|
|
|
) => {
|
|
|
|
return (
|
2022-03-07 20:45:39 +00:00
|
|
|
<button ref={ref} className={getClassName(className, variant)} {...props}>
|
2022-03-07 12:27:56 +00:00
|
|
|
{getContent(children, prependIconName, appendIconName)}
|
|
|
|
</button>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
export const AnchorButton = forwardRef<HTMLAnchorElement, AnchorButtonProps>(
|
|
|
|
(
|
|
|
|
{
|
|
|
|
variant = 'primary',
|
|
|
|
children,
|
|
|
|
className,
|
|
|
|
prependIconName,
|
|
|
|
appendIconName,
|
|
|
|
...prosp
|
|
|
|
},
|
|
|
|
ref
|
|
|
|
) => {
|
|
|
|
return (
|
|
|
|
<a ref={ref} className={getClassName(className, variant)} {...prosp}>
|
|
|
|
{getContent(children, prependIconName, appendIconName)}
|
|
|
|
</a>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
);
|