-
Notifications
You must be signed in to change notification settings - Fork 729
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
new(vx-tooltip): add Portal + demo #755
Conversation
…l listeners to useMeasure config
|
||
import Tooltip, { TooltipProps, defaultStyles } from './Tooltip'; | ||
|
||
type RectShape = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these were written before the @vx/bounds
types were added
@@ -0,0 +1,244 @@ | |||
import React, { useState, useCallback } from 'react'; | |||
import useMeasure from 'react-use-measure'; | |||
import { Tooltip, TooltipWithBounds, useTooltip, defaultStyles, Portal } from '@vx/tooltip/src'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reminder to update src
=> lib
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is fixed in #756 which set to merge into this branch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
small comment. overall lgtm
|
||
componentWillUnmount() { | ||
if (this.node && document.body) { | ||
document.body.removeChild(this.node); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can also do this.node.remove()
/> | ||
<TooltipWrapper> | ||
<TooltipComponent | ||
key={Math.random()} // needed for bounds to update correctly |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keys should be stable, predictable, and unique. Unstable keys (like those produced by Math.random()) will cause many component instances and DOM nodes to be unnecessarily recreated, which can cause performance degradation and lost state in child components.
https://reactjs.org/docs/reconciliation.html#trade-offs
Does it have to be recreated all the time?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah I think unfortunately for now, we do this in most of our demos. This forces a re-mount (😱) to force-update the bounds the component has, which basically change on every mouse move. Without this, if you start the tooltip on the left of the chart and move it to the right edge, it still thinks it has room because it's using the initial bounds.
This really can't be that great for perf because of the remount and because calling .getBoundingClientRect()
forces layout/reflow. I tried to switch to use-measure
for the boundary detection, but it only uses scroll
listeners + ResizeObserver
, so it doesn't re-compute on mouse move.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
left a comment on react-use-measure
about it cc @techniq
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IntersectionObserver
seems promising. If react-use-measure
doesn't add something, we might be able to only update the key
when the observer fires... to force an update.
I initially thought we could pre-compute the bounds based on the parent and tooltip size, but sinse the tooltip size can change size based on the contents, this wouldn't work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I initially thought we could pre-compute the bounds based on the parent and tooltip size, but since the tooltip size can change size based on the contents, this wouldn't work.
ah this is interesting, currently we use the bounds.left/top
attributes of the tooltip, rather than bounds.width/height
(which should be more stable). I took a shot at updating to use the latter and not updating key
, but hit issues in the portal where width/height
of the parent can be 0
😭
new(vx-tooltip): add useTooltipInPortal
gonna merge this to wrap it up, happy to address any concerns in a followup PR |
🚀 Enhancements
📝 Documentation
This PR
Portal
component to@vx/tooltip
useTooltip
left: 0
by default onTooltipWithBounds
which was needed for correct positioning within aPortal
/tooltip
, which demos the boundary detection +Portal
usagereact-use-measure
dependency invx-demo
)Gallery
, and to@vx/tooltip
examplesTesting
@vx/tooltip
docs; note: portal does require additional calculation complexity, but it's not too bad. Hopefully the demo will be good for showing people how to do this.Without Portal
![](https://user-images.githubusercontent.com/4496521/85064994-44a79980-b161-11ea-8176-ea0e7603e416.png)
With Portal
![](https://user-images.githubusercontent.com/4496521/85064963-38234100-b161-11ea-901e-5cf6d630a592.png)
Gif
![tooltip-portal](https://user-images.githubusercontent.com/4496521/85064678-c1864380-b160-11ea-9c80-1fd6b0ca8077.gif)
In docs
![image](https://user-images.githubusercontent.com/4496521/85064853-07430c00-b161-11ea-9aca-72eac9ab05fa.png)
In gallery
![image](https://user-images.githubusercontent.com/4496521/85064903-1c1f9f80-b161-11ea-94d2-f7a93d5d7b6a.png)
@hshoff @kristw @techniq