docbrown/app/javascript/crayons/Button/Button.jsx
Nick Taylor d6e5808dec
Created Crayons Button Preact component (#6987)
* wip <Button > component.

* wip button components.

* Fixed issue when icon does not exist.

* Removed subfolder JSX for Preact components in Storybook sidebar.

* Touched up some Storybook stories.

* Now <Button /> component supports a or button for HTML.

* Now the <Button /> component supports the disabled prop

* A nice little refactor.

* Added onClick, onMouseOver, onMouseOut, onFocus and onBlur events to the <Button /> component.

* Set the cursor to default when a <Button /> component is disabled.

* Added tests for <Button /> component.

* Added tests for <SecondaryButton />, <OutlineButton /> and <DangerButton />.

* Updated disabled cursor.

* Removed link href when button is disabled and is an <a />.

* Added the icon alone option for the <Button /> component.

* Now active and hover states are disabled for <Button /> when an HTML button is rendered.

* Now the disabled <Button /> component deactivates hover/active states properly.

* Removed global button hover styling as per @ludwiczakpawel's request.

* Renamed the as prop to tagName.

* Removed components that were wrapping different variants.
2020-04-03 10:49:01 -04:00

110 lines
2.3 KiB
JavaScript

import { h } from 'preact';
import PropTypes from 'prop-types';
import { defaultChildrenPropTypes } from '../../src/components/common-prop-types';
function getAdditionalClassNames({
variant,
className,
icon,
disabled,
children,
}) {
let additionalClassNames = '';
if (variant && variant.length > 0 && variant !== 'primary') {
additionalClassNames += ` crayons-btn--${variant}`;
}
if (icon) {
additionalClassNames +=
children.length > 0
? ' crayons-btn--icon-left'
: ' crayons-btn--icon-alone';
}
if (disabled) {
additionalClassNames += ' crayons-btn--disabled';
}
if (className && className.length > 0) {
additionalClassNames += ` ${className}`;
}
return additionalClassNames;
}
export const Button = ({
children,
variant = 'primary',
tagName = 'button',
className,
icon,
url,
buttonType,
disabled,
onClick,
onMouseOver,
onMouseOut,
onFocus,
onBlur,
}) => {
const ComponentName = tagName;
const Icon = icon;
const otherProps =
tagName === 'button'
? { type: buttonType, disabled }
: { href: disabled ? undefined : url };
return (
<ComponentName
className={`crayons-btn${getAdditionalClassNames({
variant,
className,
icon,
disabled: tagName === 'a' && disabled,
children,
})}`}
onClick={onClick}
onMouseOver={onMouseOver}
onMouseOut={onMouseOut}
onFocus={onFocus}
onBlur={onBlur}
{...otherProps}
>
{Icon && <Icon />}
{children}
</ComponentName>
);
};
Button.displayName = 'Button';
Button.defaultProps = {
className: undefined,
icon: undefined,
url: undefined,
buttonType: 'button',
disabled: false,
onClick: undefined,
onMouseOver: undefined,
onMouseOut: undefined,
onFocus: undefined,
onBlur: undefined,
};
Button.propTypes = {
children: defaultChildrenPropTypes.isRequired,
variant: PropTypes.oneOf(['primary', 'secondary', 'outlined', 'danger'])
.isRequired,
tagName: PropTypes.oneOf(['a', 'button']).isRequired,
className: PropTypes.string,
icon: PropTypes.node,
url: PropTypes.string,
buttonType: PropTypes.string,
disabled: PropTypes.bool,
onClick: PropTypes.func,
onMouseOver: PropTypes.func,
onMouseOut: PropTypes.func,
onFocus: PropTypes.func,
onBlur: PropTypes.func,
};