vega-frontend-monorepo/libs/ui-toolkit/src/components/button/button.tsx

189 lines
5.8 KiB
TypeScript
Raw Normal View History

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';
import {
includesLeftPadding,
includesRightPadding,
includesBorderWidth,
} from '../../utils/class-names';
interface CommonProps {
2022-03-01 09:26:26 +00:00
children?: React.ReactNode;
variant?: 'primary' | 'secondary' | 'accent' | 'inline' | 'inline-link';
2022-03-01 09:26:26 +00:00
className?: string;
2022-03-02 09:56:05 +00:00
prependIconName?: IconName;
appendIconName?: IconName;
2022-03-01 09:26:26 +00:00
}
export interface ButtonProps
extends ButtonHTMLAttributes<HTMLButtonElement>,
CommonProps {}
export interface AnchorButtonProps
extends AnchorHTMLAttributes<HTMLAnchorElement>,
CommonProps {}
2022-03-01 09:26:26 +00:00
const getClassName = (
className: CommonProps['className'],
variant: CommonProps['variant']
) => {
const paddingLeftProvided = includesLeftPadding(className);
const paddingRightProvided = includesRightPadding(className);
const borderWidthProvided = includesBorderWidth(className);
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',
'hover:underline',
'disabled:no-underline',
2022-03-03 14:48:40 +00:00
'transition-all',
2022-03-01 09:26:26 +00:00
],
{
'text-ui': variant !== 'inline-link',
'no-underline': variant !== 'inline-link',
'pl-28': !(
paddingLeftProvided ||
variant === 'inline' ||
variant === 'inline-link'
),
'pr-28': !(
paddingRightProvided ||
variant === 'inline' ||
variant === 'inline-link'
),
border: !borderWidthProvided,
2022-03-03 11:11:36 +00:00
'hover:border-black dark:hover:border-white':
variant !== 'inline' && variant !== 'inline-link',
2022-03-03 14:48:40 +00:00
'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' ||
variant === 'inline-link',
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',
'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
'pl-4': variant === 'inline' && !paddingLeftProvided,
'pr-4': variant === 'inline' && !paddingRightProvided,
'border-0':
(variant === 'inline' || variant === 'inline-link') &&
!borderWidthProvided,
underline: variant === 'inline' || variant === 'inline-link',
2022-03-01 09:26:26 +00:00
'hover:no-underline': variant === 'inline',
2022-03-04 16:21:24 +00:00
'hover:border-transparent dark:hover:border-transparent':
variant === 'inline' || variant === 'inline-link',
2022-03-04 16:21:24 +00:00
'active:border-transparent dark:active:border-transparent':
variant === 'inline' || variant === 'inline-link',
'active:text-black dark:active:text-vega-yellow':
variant === 'inline' || variant === 'inline-link',
'text-black-95 dark:text-white-95':
variant === 'inline' || variant === 'inline-link',
'hover:text-black hover:dark:text-white':
variant === 'inline' || variant === 'inline-link',
2022-03-03 14:48:40 +00:00
'disabled:bg-black-10 dark:disabled:bg-white-10':
variant !== 'inline' && variant !== 'inline-link',
2022-03-07 13:27:17 +00:00
'disabled:text-black-60 dark:disabled:text-white-60':
variant !== 'inline' && variant !== 'inline-link',
2022-03-07 13:27:17 +00:00
'disabled:border-black-25 dark:disabled:border-white-25':
variant !== 'inline' && variant !== 'inline-link',
2022-03-01 09:26:26 +00:00
},
className
);
};
const getContent = (
children: React.ReactNode,
prependIconName?: IconName,
appendIconName?: IconName
) => {
2022-03-02 09:56:05 +00:00
const iconName = prependIconName || appendIconName;
if (iconName === undefined) {
return children;
2022-03-02 09:56:05 +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-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-01 09:26:26 +00:00
);
};
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
(
{
variant = 'primary',
Feat/63 Deal ticket (#82) * scaffold dealticket package, remove trading views from react-helpers * add deal ticket component, add intent utils, expand dialog and form group styles * add splash component, show market not found message if market doesnt exist * tidy up error handling * add handleError method for vega tx hook * add better testname for provider test, flesh out tests a bit more for deal ticket * Add unit tests for useVegaTransaction and useOrderSubmit hooks * add wrapper component for order dialog styles * add vega styled loader to ui toolkit and use in order dialog * add title prop to order dialog * split limit and market tickets into own files * add button radio component * revert dialog styles * move splash component to ui-toolkit, add story * convert intent to enum * Make button always type=button unless type prop is passed * inline filter logic for tif selector * add date-fns, add datetime to helpers * add order types to wallet package, make price undefined if order type is market * use enums in deal ticket logic * tidy up order state by moving submit and transaction hooks out of deal ticket * add comment for dialog styles * remove decimal from price input * add types package, delete old generated types from trading project * rename types package to graphql * update generate command to point to correct locations * fix use order submit test * use intent shadow helper * remove date-fns and format manually, update submit button error to use input-error * remove stray console.log
2022-03-17 19:35:46 +00:00
type = 'button',
children,
className,
prependIconName,
appendIconName,
...props
},
ref
) => {
return (
Feat/63 Deal ticket (#82) * scaffold dealticket package, remove trading views from react-helpers * add deal ticket component, add intent utils, expand dialog and form group styles * add splash component, show market not found message if market doesnt exist * tidy up error handling * add handleError method for vega tx hook * add better testname for provider test, flesh out tests a bit more for deal ticket * Add unit tests for useVegaTransaction and useOrderSubmit hooks * add wrapper component for order dialog styles * add vega styled loader to ui toolkit and use in order dialog * add title prop to order dialog * split limit and market tickets into own files * add button radio component * revert dialog styles * move splash component to ui-toolkit, add story * convert intent to enum * Make button always type=button unless type prop is passed * inline filter logic for tif selector * add date-fns, add datetime to helpers * add order types to wallet package, make price undefined if order type is market * use enums in deal ticket logic * tidy up order state by moving submit and transaction hooks out of deal ticket * add comment for dialog styles * remove decimal from price input * add types package, delete old generated types from trading project * rename types package to graphql * update generate command to point to correct locations * fix use order submit test * use intent shadow helper * remove date-fns and format manually, update submit button error to use input-error * remove stray console.log
2022-03-17 19:35:46 +00:00
<button
ref={ref}
className={getClassName(className, variant)}
type={type}
{...props}
>
{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>
);
}
);