Skip to content

Instantly share code, notes, and snippets.

@theY4Kman
Created August 21, 2018 00:47
Show Gist options
  • Save theY4Kman/09f24a41bd7a67fe6a777dbf99a68070 to your computer and use it in GitHub Desktop.
Save theY4Kman/09f24a41bd7a67fe6a777dbf99a68070 to your computer and use it in GitHub Desktop.
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
const HoverContext = React.createContext({
hovering: null,
hovered: null,
});
export
class Hover extends React.Component {
constructor(props) {
super(props);
this.ref = React.createRef();
this.state = { hovering: false, hovered: false };
}
componentDidMount() {
this.child = ReactDOM.findDOMNode(this.ref.current);
this.child.addEventListener('mouseenter', this.onMouseEnter);
this.child.addEventListener('mouseleave', this.onMouseLeave);
}
componentWillUnmount() {
if (this.child) {
this.child.removeEventListener('mouseenter', this.onMouseEnter);
this.child.removeEventListener('mouseleave', this.onMouseLeave);
this.setState({ hovering: false, hovered: false });
}
}
onMouseEnter = () => {
this.setState({ hovering: true, hovered: true });
};
onMouseLeave = () => {
this.setState({ hovering: false });
};
render() {
const { children } = this.props;
const { hovering, hovered } = this.state;
return (
<HoverContext.Provider value={{ hovering, hovered }}>
{React.cloneElement(children, { ref: this.ref })}
</HoverContext.Provider>
);
}
}
Hover.propTypes = {
children: PropTypes.node.isRequired,
};
export
const BeforeHover = ({ children, defaultRender }) => (
<HoverContext.Consumer>
{({ hovered }) => (
(hovered === false || (hovered === null && defaultRender)) && children
)}
</HoverContext.Consumer>
);
BeforeHover.propTypes = {
children: PropTypes.node.isRequired,
defaultRender: PropTypes.bool,
};
BeforeHover.defaultProps = {
defaultRender: false,
};
export
const AfterHover = ({ children, defaultRender }) => (
<HoverContext.Consumer>
{({ hovered }) => (
(hovered || (hovered === null && defaultRender)) && children
)}
</HoverContext.Consumer>
);
AfterHover.propTypes = {
children: PropTypes.node.isRequired,
defaultRender: PropTypes.bool,
};
AfterHover.defaultProps = {
defaultRender: true,
};
export
const Hovering = ({ children }) => (
<HoverContext.Consumer>
{({ hovering }) => (
hovering && children
)}
</HoverContext.Consumer>
);
Hovering.propTypes = {
children: PropTypes.node.isRequired,
};
export
const NotHovering = ({ children }) => (
<HoverContext.Consumer>
{({ hovering }) => (
!hovering && children
)}
</HoverContext.Consumer>
);
NotHovering.propTypes = {
children: PropTypes.node.isRequired,
};
import React from 'react';
import PropTypes from 'prop-types';
import { Tooltip as BaseTooltip } from 'material-ui';
import { BeforeHover, AfterHover, Hovering, NotHovering } from './Hover';
const Tooltip = ({ children, ...props }) => (
<React.Fragment>
<BeforeHover>
{children}
</BeforeHover>
<AfterHover>
<BaseTooltip {...props}>{children}</BaseTooltip>
</AfterHover>
</React.Fragment>
);
const Tooltip = ({ children, ...props }) => (
<React.Fragment>
<NotHovering>
{children}
</NotHovering>
<Hovering>
<BaseTooltip {...props}>{children}</BaseTooltip>
</Hovering>
</React.Fragment>
);
Tooltip.propTypes = {
children: PropTypes.node,
};
Tooltip.defaultProps = {
children: null,
};
export default Tooltip;
@theY4Kman
Copy link
Author

I guess I was trying out different things in Tooltip.js, which is prolly why I'm redefining the fucker. Using const no less — she definitely ain't compiling :P

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment