ohif-viewer/platform/ui/src/components/Button/Button.tsx

150 lines
3.8 KiB
TypeScript
Raw Normal View History

2020-05-15 14:29:27 +02:00
import React, { useRef } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import * as ButtonEnums from './ButtonEnums';
const sizeClasses = {
[ButtonEnums.size.small]: 'h-[26px] text-[13px]',
[ButtonEnums.size.medium]: 'h-[32px] text-[14px]',
};
const layoutClasses =
'box-content inline-flex flex-row items-center justify-center gap-[5px] justify center px-[10px] outline-none rounded';
const baseFontTextClasses =
'leading-[1.2] font-sans text-center whitespace-nowrap';
const fontTextClasses = {
[ButtonEnums.type.primary]: classnames(baseFontTextClasses, 'font-semibold'),
[ButtonEnums.type.secondary]: classnames(baseFontTextClasses, 'font-400'),
};
const baseEnabledEffectClasses =
'transition duration-300 ease-in-out focus:outline-none';
const enabledEffectClasses = {
[ButtonEnums.type.primary]: classnames(
baseEnabledEffectClasses,
'hover:bg-customblue-80 active:bg-customblue-40'
),
[ButtonEnums.type.secondary]: classnames(
baseEnabledEffectClasses,
'hover:bg-customblue-50 active:bg-customblue-20'
),
};
const baseEnabledClasses = 'text-white';
const enabledClasses = {
[ButtonEnums.type.primary]: classnames(
'bg-primary-main',
baseEnabledClasses,
enabledEffectClasses[ButtonEnums.type.primary]
),
[ButtonEnums.type.secondary]: classnames(
'bg-customblue-30',
baseEnabledClasses,
enabledEffectClasses[ButtonEnums.type.secondary]
),
};
const disabledClasses =
'bg-inputfield-placeholder text-common-light cursor-default';
2020-03-04 23:16:51 +01:00
const defaults = {
color: 'default',
disabled: false,
rounded: 'small',
size: ButtonEnums.size.medium,
type: ButtonEnums.type.primary,
};
const Button = ({
children,
size = defaults.size,
disabled = defaults.disabled,
type = defaults.type,
startIcon: startIconProp,
endIcon: endIconProp,
name,
className,
onClick,
}) => {
feat: nuke UI project; start new with updated tooling BREAKING_CHANGE (#1468) BREAKING_CHANGE * initial structure for components rewrite * WIP Input * WIP Label * add button props * add label class name * fix dependency * new examples buttonModules & buttonEmotion + refac * clean up to merge initial code into base branch * remove unused file * extend default theme -- add new colors * chore: prettier formatting * chore: try to exclude feature branch PRs * chore: suggest toml syntax highlighting extension * chore: capture yarn.lock changes * docs: condense readme * chore: update deploy preview to build docz component library * chore: Add component library to deploy preview index * chore: fix invalid tailwindcss config * chore: try tweaking toml to kickstart preview * chore: revert * chore: fix formatting of file index * chore: don't waste precious build minutes on a broken build * chore: chmod build-and-deploy.sh * ci: nuke circleci until we need the workflows on master * debug lerna commands * remove redundant yarn commands * try nohoist * revert tests * attempt to resolve import issue * force update yarn lock * try new workarounds for yarn version * another workaround * shift vtk to extension repo deps * catch vtk addition * update lock * Try older yarn version * try again * debugging * fix: yarn doctor warnings * learn some life lessons from the yarn docs * clean up netlify.toml * clean up netlify.toml * yarn package doctor react-dom * yarn doctor: missing peer dep * yarn doctor, satisfying webpack loader peer deps * fix docz base path for deploy-preview * yarn docter: replaced prePublishOnly usage * More yarn doctoring * ignore .yarn directory * fix last yarn doctor warning * updated yarn lock Co-authored-by: Rodrigo Antinarelli <rodrigoantinarelli@gmail.com>
2020-03-02 19:37:00 +01:00
const startIcon = startIconProp && (
<>
2020-05-15 14:29:27 +02:00
{React.cloneElement(startIconProp, {
className: classnames('w-4 h-4 fill-current'),
})}
</>
2020-05-15 14:29:27 +02:00
);
const endIcon = endIconProp && (
<>
2020-05-15 14:29:27 +02:00
{React.cloneElement(endIconProp, {
className: classnames('w-4 h-4 fill-current'),
})}
</>
);
2020-05-15 14:29:27 +02:00
const buttonElement = useRef(null);
const handleOnClick = e => {
2020-04-02 20:52:41 +02:00
buttonElement.current.blur();
if (!disabled) {
onClick(e);
2020-04-02 20:52:41 +02:00
}
};
const finalClassName = classnames(
layoutClasses,
fontTextClasses[type],
disabled ? disabledClasses : enabledClasses[type],
sizeClasses[size],
children ? 'min-w-[32px]' : '', // minimum width for buttons with text; icon only button does NOT get a minimum width
className
);
return (
<button
className={finalClassName}
disabled={disabled}
2020-05-15 14:29:27 +02:00
ref={buttonElement}
onClick={handleOnClick}
data-cy={`${name}-btn`}
>
{startIcon}
{children}
{endIcon}
</button>
);
};
Button.defaultProps = {
disabled: false,
children: '',
onClick: () => {},
type: defaults.type,
size: defaults.size,
};
Button.propTypes = {
/** What is inside the button, can be text or react component */
2020-02-14 23:46:27 +01:00
children: PropTypes.node,
/** Callback to be called when the button is clicked */
onClick: PropTypes.func.isRequired,
/** Button size */
size: PropTypes.oneOf([ButtonEnums.size.medium, ButtonEnums.size.small]),
/** Whether the button should be disabled */
2020-02-14 23:46:27 +01:00
disabled: PropTypes.bool,
/** Button type */
type: PropTypes.oneOf([ButtonEnums.type.primary, ButtonEnums.type.secondary]),
name: PropTypes.string,
/** Button start icon name - if any icon is specified */
2020-02-14 23:46:27 +01:00
startIcon: PropTypes.node,
/** Button end icon name - if any icon is specified */
2020-02-14 23:46:27 +01:00
endIcon: PropTypes.node,
/** Additional TailwindCSS classnames */
2020-03-03 23:36:22 +01:00
className: PropTypes.string,
};
export default Button;