Repository URL to install this package:
|
Version:
7.11.0 ▾
|
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
export const buttonVariants = [
'accent',
'flatAccent',
'green',
'blue',
'white',
'whiteWithBorder',
'yellow',
'linkBlue',
'linkWhite',
'linkDark',
'linkRed',
'linkBanner',
];
export const buttonTargets = ['_blank', '_self', '_top', '_parent'];
export const defaultButtonVariant = 'accent';
export const buttonDimensions = ['small', 'compact', 'very-compact'];
class Button extends Component {
static propTypes = {
children: PropTypes.any,
variant: PropTypes.oneOf(buttonVariants),
modifier: PropTypes.string,
className: PropTypes.string,
dimension: PropTypes.oneOf(buttonDimensions),
type: PropTypes.oneOf(['button', 'submit', 'reset']),
focus: PropTypes.bool,
hover: PropTypes.bool,
active: PropTypes.bool,
inputButtonClass: PropTypes.oneOf(['inputButton', 'loading']),
responsive: PropTypes.bool,
target: PropTypes.oneOf(buttonTargets),
/** Renders the button as an \<a\> tag with this value as href attribute. If possible, it's preferable to use the <a href="#link">Link</a> component */
href: (props, propName) => {
if (props[propName]) {
// Only allow the default value
if (props.type !== Button.defaultProps.type) {
return new Error('Buttons with an href cannot have a type property because they will be rendered as links');
}
if (typeof props[propName] !== 'string') {
return new Error(`The property ${propName} must be a string`);
}
}
},
};
static defaultProps = {
children: null,
variant: defaultButtonVariant,
modifier: null,
className: null,
dimension: null,
type: 'button',
focus: false,
hover: false,
active: false,
inputButtonClass: null,
responsive: null,
href: null,
target: '_self',
};
componentDidMount() {
// Normalises the behaviour so that button is focused on click also on Safari and Firefox on Mac.
// See: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#Clicking_and_focus
this.button.addEventListener('mousedown', () => {
// set timeout required as the component might be re-rendered
this.focusTimeout = setTimeout(() => {
if (this.button) {
this.button.focus();
}
});
});
}
componentDidUnMount() {
if (this.focusTimeout) {
clearTimeout(this.focusTimeout);
}
}
render() {
const {
responsive,
variant,
modifier,
className,
dimension,
type,
focus,
hover,
active,
inputButtonClass,
href,
target,
...props
} = this.props;
const componentClassName = classnames(
'Button',
{
[`Button--${variant}`]: variant,
[`Button--${modifier}`]: modifier,
[`Button--${dimension}`]: dimension,
[`Button--${inputButtonClass}`]: inputButtonClass,
'Button--responsive': responsive,
'Button--focus': focus,
'Button--hover': hover,
'Button--active': active,
},
className
);
return href ? (
<a
ref={button => {
this.button = button;
}}
className={componentClassName}
href={href}
target={target}
rel="noopener noreferrer"
{...props}
>
<span className="Button-contentWrapper">{this.props.children}</span>
</a>
) : (
<button
ref={button => {
this.button = button;
}}
className={componentClassName}
type={type}
{...props}
>
<span className="Button-contentWrapper">{this.props.children}</span>
</button>
);
}
}
export default Button;