wix-style-react
Version:
191 lines (166 loc) • 4.86 kB
JavaScript
import React from 'react';
import PropTypes from 'prop-types';
import { st, classes } from './Tag.st.css';
import CloseButton from '../CloseButton';
import Text from '../Text';
import { dataHooks } from './Tag.helpers';
import { FontUpgradeContext } from '../FontUpgrade/context';
import { generateDataAttr } from '../utils/generateDataAttr';
const tagToTextSize = {
tiny: 'tiny',
small: 'small',
medium: 'small',
large: 'medium',
};
const noop = () => ({});
/**
* A Tag component
*/
class Tag extends React.PureComponent {
static displayName = 'Tag';
_renderThumb() {
const { thumb } = this.props;
return thumb ? (
<span data-hook={dataHooks.thumb} className={classes.thumb}>
{thumb}
</span>
) : null;
}
_renderText({ isMadefor }) {
const { size, children, disabled, theme } = this.props;
return (
<Text
skin={disabled ? 'disabled' : 'standard'}
light={theme === 'dark'}
secondary={theme !== 'dark'}
ellipsis
size={tagToTextSize[size]}
weight={isMadefor || size === 'tiny' ? 'thin' : 'normal'}
className={classes.text}
dataHook={dataHooks.text}
>
{children}
</Text>
);
}
_renderRemoveButton() {
const { removable, disabled, size, theme } = this.props;
if (removable) {
return (
<CloseButton
size={size === 'large' ? 'medium' : 'small'}
skin={theme === 'dark' ? 'light' : 'dark'}
disabled={disabled}
dataHook={dataHooks.removeButton}
className={classes.removeButton}
onClick={this._handleRemoveClick}
/>
);
} else {
return null;
}
}
_handleRemoveClick = event => {
const { onRemove, id } = this.props;
event.stopPropagation();
onRemove(id);
};
_handleOnClick = event => {
const { id, onClick } = this.props;
return onClick && onClick(id, event);
};
render() {
const {
id,
onClick,
maxWidth,
dataHook,
size,
disabled,
theme,
thumb,
removable,
className,
} = this.props;
const clickable = !!onClick;
const hoverable = !disabled && !!onClick;
return (
<FontUpgradeContext.Consumer>
{({ active: isMadefor }) => (
<span
className={st(
classes.root,
{
withRemoveButton: removable,
withThumb: !!thumb,
disabled,
clickable,
hoverable,
size,
theme,
},
className,
)}
{...generateDataAttr({ ...this.props, hoverable, clickable }, [
'size',
'disabled',
'theme',
'hoverable',
'clickable',
])}
data-hook={dataHook}
id={id}
onClick={this._handleOnClick}
style={{ maxWidth: `${maxWidth}px` }}
>
{this._renderThumb()}
{this._renderText({ isMadefor })}
{this._renderRemoveButton()}
</span>
)}
</FontUpgradeContext.Consumer>
);
}
}
Tag.propTypes = {
/** Applies a data-hook HTML attribute that can be used in the tests */
dataHook: PropTypes.string,
/** Sets the text of the tag */
children: PropTypes.node.isRequired,
/** Specifies whether the tag should be disabled */
disabled: PropTypes.bool,
/** Assigns an unique identifier for the tag */
id: PropTypes.string.isRequired,
/** Defines a callback function which is called whenever a tag component is clicked.
* It passes the id property as the first parameter and a mouse event as second parameter. */
onClick: PropTypes.func,
/** Defines a callback function which is called when removing the tag. It passes the id property as a parameter. */
onRemove: PropTypes.func,
/** Specifies whether the tag is removable or not. If enabled, a small clickable X icon is displayed on the right side of a component. */
removable: PropTypes.bool,
/** Controls the size of the component */
size: PropTypes.oneOf(['tiny', 'small', 'medium', 'large']),
/** Sets the theme of the component */
theme: PropTypes.oneOf([
'standard',
'error',
'warning',
'dark',
'neutral',
'success',
'light',
'lightOutlined',
]),
/** Displays a thumbnail at the front of a tag label. Usually contain icons or `<Avatar/>`. */
thumb: PropTypes.element,
/** Sets a maximum tag width in pixels */
maxWidth: PropTypes.number,
/** Specifies a CSS class name to be appended to the component’s root element */
className: PropTypes.string,
};
Tag.defaultProps = {
size: 'small',
removable: true,
theme: 'standard',
};
export default Tag;