Allow tooltips without wrappers for every child

dev 2.0.0-beta.20
Vitaliy Filippov 2019-03-05 21:34:16 +03:00
parent 2427d05568
commit 36fd012442
2 changed files with 42 additions and 6 deletions

View File

@ -55,6 +55,7 @@ const tooltipFactory = (options = {}) => {
PropTypes.node, PropTypes.node,
]), ]),
tooltipDelay: PropTypes.number, tooltipDelay: PropTypes.number,
tooltipForChildren: PropTypes.bool,
tooltipHideOnClick: PropTypes.bool, tooltipHideOnClick: PropTypes.bool,
tooltipOnFocus: PropTypes.bool, tooltipOnFocus: PropTypes.bool,
tooltipPosition: PropTypes.oneOf(Object.keys(POSITION).map(key => POSITION[key])), tooltipPosition: PropTypes.oneOf(Object.keys(POSITION).map(key => POSITION[key])),
@ -75,6 +76,7 @@ const tooltipFactory = (options = {}) => {
visible: false, visible: false,
top: 0, top: 0,
left: 0, left: 0,
tooltip: '',
}; };
componentWillUnmount() { componentWillUnmount() {
@ -193,6 +195,33 @@ const tooltipFactory = (options = {}) => {
if (this.props.onMouseLeave) this.props.onMouseLeave(event); if (this.props.onMouseLeave) this.props.onMouseLeave(event);
}; };
handleMouseEnterForChildren = (event) => {
let el = event.target;
while (el && (!el.getAttribute || !el.getAttribute('tooltip'))) {
el = el.parentNode;
}
if (el) {
if (this.timeout) {
clearTimeout(this.timeout);
this.timeout = null;
}
this.setState({ tooltip: el.getAttribute('tooltip') });
const pos = this.calculatePosition(el);
if (!this.state.visible) {
this.activate(pos);
} else if (this.state.position !== pos.position ||
this.state.top !== pos.top || this.state.left !== pos.left) {
this.setState({ active: false, visible: false }, () => this.activate(pos));
}
}
};
handleMouseLeaveForChildren = () => {
this.timeout = setTimeout(() => {
this.deactivate();
}, 300);
};
handleClick = (event) => { handleClick = (event) => {
if (this.props.tooltipHideOnClick && this.state.active) { if (this.props.tooltipHideOnClick && this.state.active) {
this.deactivate(); this.deactivate();
@ -216,6 +245,7 @@ const tooltipFactory = (options = {}) => {
onMouseEnter, // eslint-disable-line no-unused-vars onMouseEnter, // eslint-disable-line no-unused-vars
onMouseLeave, // eslint-disable-line no-unused-vars onMouseLeave, // eslint-disable-line no-unused-vars
tooltip, tooltip,
tooltipForChildren,
tooltipOnFocus, // eslint-disable-line no-unused-vars tooltipOnFocus, // eslint-disable-line no-unused-vars
tooltipDelay, // eslint-disable-line no-unused-vars tooltipDelay, // eslint-disable-line no-unused-vars
tooltipHideOnClick, // eslint-disable-line no-unused-vars tooltipHideOnClick, // eslint-disable-line no-unused-vars
@ -238,6 +268,9 @@ const tooltipFactory = (options = {}) => {
if (tooltipOnFocus) { if (tooltipOnFocus) {
childProps.onFocus = this.handleMouseEnter; childProps.onFocus = this.handleMouseEnter;
childProps.onBlur = this.handleMouseLeave; childProps.onBlur = this.handleMouseLeave;
} else if (tooltipForChildren) {
childProps.onMouseOver = this.handleMouseEnterForChildren;
childProps.onMouseOut = this.handleMouseLeaveForChildren;
} else { } else {
childProps.onMouseEnter = this.handleMouseEnter; childProps.onMouseEnter = this.handleMouseEnter;
childProps.onMouseLeave = this.handleMouseLeave; childProps.onMouseLeave = this.handleMouseLeave;
@ -246,8 +279,9 @@ const tooltipFactory = (options = {}) => {
const shouldPass = typeof ComposedComponent !== 'string' && defaultPassthrough; const shouldPass = typeof ComposedComponent !== 'string' && defaultPassthrough;
const finalProps = shouldPass ? { ...childProps, theme } : childProps; const finalProps = shouldPass ? { ...childProps, theme } : childProps;
return React.createElement(ComposedComponent, finalProps, children, return (<React.Fragment>
visible && ( {React.createElement(ComposedComponent, finalProps, children)}
{visible && (
<Portal> <Portal>
<span <span
ref={this.setTooltipNode} ref={this.setTooltipNode}
@ -255,11 +289,13 @@ const tooltipFactory = (options = {}) => {
data-react-toolbox="tooltip" data-react-toolbox="tooltip"
style={active ? { top, left, transform } : { top: '-1000px', left: 0 }} style={active ? { top, left, transform } : { top: '-1000px', left: 0 }}
> >
<span className={theme.tooltipInner}>{tooltip}</span> <span className={theme.tooltipInner}>
{this.state.tooltip || this.props.tooltip}
</span>
</span> </span>
</Portal> </Portal>
), )}
); </React.Fragment>);
} }
} }

View File

@ -2,7 +2,7 @@
"name": "react-toolbox", "name": "react-toolbox",
"description": "A set of React components implementing Google's Material Design specification with the power of CSS Modules.", "description": "A set of React components implementing Google's Material Design specification with the power of CSS Modules.",
"homepage": "http://www.react-toolbox.io", "homepage": "http://www.react-toolbox.io",
"version": "2.0.0-beta.19", "version": "2.0.0-beta.20",
"main": "./lib", "main": "./lib",
"module": "./components", "module": "./components",
"author": { "author": {