Skip to content

Commit

Permalink
fix(xo-web/Tooltip): don't hide on changing children prop
Browse files Browse the repository at this point in the history
Due to the way React works, `props.children` always change even if it
will resolve to the same DOM node.

The implementation is therefore updated to check equality on DOM nodes
directly.
  • Loading branch information
julien-f committed Oct 2, 2024
1 parent 9321b04 commit 6ca44fe
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 32 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

> Users must be able to say: “I had this issue, happy to know it's fixed”
- [Tooltip] Fix randomly disappearing tooltips

### Packages to release

> When modifying a package, add it here with its release type.
Expand All @@ -32,5 +34,6 @@
<!--packages-start-->

- @xen-orchestra/log minor
- xo-web patch

<!--packages-end-->
69 changes: 37 additions & 32 deletions packages/xo-web/src/common/tooltip/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,53 +62,51 @@ export default class Tooltip extends Component {
tagName: PropTypes.string,
}

_node = null

componentDidMount() {
this._addListeners()
this._updateListeners()
}

componentWillUnmount() {
this._removeListeners()
}

componentWillReceiveProps(props) {
if (props.children !== this.props.children) {
this._removeListeners()
}
}

componentDidUpdate(prevProps) {
if (prevProps.children !== this.props.children) {
this._addListeners()
}
this._updateListeners()
}

_addListeners() {
const node = (this._node = ReactDOM.findDOMNode(this))

// 2020-06-15: Use pointer events instead of mouse events to workaround
// Chrome not firing any mouse event on disabled inputs. Pointer events
// should be correctly fired on most browsers and are similar to mouse
// events on mouse-controlled devices.
// https://github.com/reach/reach-ui/issues/564#issuecomment-620502842
// https://caniuse.com/#feat=mdn-api_pointerevent
node.addEventListener('pointerenter', this._showTooltip)
node.addEventListener('pointerleave', this._hideTooltip)
node.addEventListener('pointermove', this._updateTooltip)
_updateListeners() {
// eslint-disable-next-line react/no-find-dom-node
const node = ReactDOM.findDOMNode(this)

if (node !== this._node) {
this._removeListeners()

this._node = node
if (node !== null) {
// 2020-06-15: Use pointer events instead of mouse events to workaround
// Chrome not firing any mouse event on disabled inputs. Pointer events
// should be correctly fired on most browsers and are similar to mouse
// events on mouse-controlled devices.
// https://github.com/reach/reach-ui/issues/564#issuecomment-620502842
// https://caniuse.com/#feat=mdn-api_pointerevent
node.addEventListener('pointerenter', this._showTooltip)
node.addEventListener('pointerleave', this._hideTooltip)
node.addEventListener('pointermove', this._updateTooltip)
}
}
}

_removeListeners() {
const node = this._node
this._hideTooltip()

if (!node) {
return
const node = this._node
if (node !== null) {
node.removeEventListener('pointerenter', this._showTooltip)
node.removeEventListener('pointerleave', this._hideTooltip)
node.removeEventListener('pointermove', this._updateTooltip)
}

node.removeEventListener('pointerenter', this._showTooltip)
node.removeEventListener('pointerleave', this._hideTooltip)
node.removeEventListener('pointermove', this._updateTooltip)

this._node = null
}

_showTooltip = () => {
Expand All @@ -123,10 +121,17 @@ export default class Tooltip extends Component {
}

_hideTooltip = () => {
instance.setState({ show: false })
if (instance !== undefined) {
instance.setState({ show: false })
}
}

_updateTooltip = event => {
if (instance === undefined) {
return
}

// eslint-disable-next-line react/no-find-dom-node
const node = ReactDOM.findDOMNode(instance)
const result = getPosition(event, event.currentTarget, node, instance.state.place, 'solid', {})

Expand Down

0 comments on commit 6ca44fe

Please sign in to comment.