-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Popover: make more reactive to prop changes, avoid unnecessary updates #43335
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
Conversation
|
Size Change: +190 B (0%) Total Size: 1.24 MB
ℹ️ View Unchanged
|
85eb8df to
4bf6dfc
Compare
3054620 to
7c6596d
Compare
7c6596d to
526f465
Compare
526f465 to
02c24d6
Compare
fc5342e to
71196ee
Compare
Popover: make more reactive to prop changes, avoid unnecessary updates
Popover: make more reactive to prop changes, avoid unnecessary updatese5379a5 to
c734279
Compare
| }; | ||
|
|
||
| export const getReferenceOwnerDocument = ( { | ||
| // @ts-ignore |
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.
For now, I haven't added types or JSDocs because I'm planning on rewriting this component to TypeScript relatively soon (plus, I hope we can get rid of a few permutations soon enough)
c734279 to
f6cf77d
Compare
mirka
left a comment
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.
Great work! I found the code to be relatively readable, given the complexity. The changes you described make sense, and I appreciate that you documented all the reasoning in detail.
I did some testing in Storybook/Editor and nothing jumped out to me.
Not sure if this is relevant to the PR, but I did notice this issue in the iframe story when taking these steps (the order matters):
- Set
position="middle left". - Set
noArrow=false. - Arrow position is wrong.
CleanShot.2022-08-30.at.22.03.02.mp4
I'll leave to you to decide if you want more eyes on this PR, or if the issue above should be addressed 👍
| const isExpanded = expandOnMobile && isMobileViewport; | ||
| const hasArrow = ! isExpanded && ! noArrow; | ||
| const normalizedPlacementFromProps = position | ||
| ? positionToPlacement( position ) |
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.
Not an issue introduced in this PR, but what is supposed to happen when noArrow=false and position="middle center"?
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.
Good question — I don't think that floating-ui supports an equivalent position.
The plan is to:
- convert all usages of
Popoverto useplacementinstead ofposition - mark
positionas deprecated / non-supported - therefore, avoiding spending time on fixing it unless more reports are filed 😅
f6cf77d to
5f28709
Compare
Well spotted! I took a quick look and the problem doesn't seem to be related to I'll look more into it and see if:
|
|
Alright, mystery solved! The iframe's offset needs to be manually added to the arrow's position (which is weird, but it's probably a consequence of the other hacks that are being done to offset the popover in the first place — I have the feeling that #42950 could fix this quirk) I'll merge this PR once CI is ✅ |
a2d5c82 to
1c0b7c9
Compare
…enceElement to be stored in state
1c0b7c9 to
1de9502
Compare


What?
Tracked in #42770
Rewrite
Popoverinternals (especially effect dependencies and forced updates) to make component more reactive to external change, but also to avoid unnecessary updates.Why?
Looking at
Popoverits code looks quite complex, with many updates fragmented across different hooks with different dependencies. The changes in this PR aim at:How?
An important concept to understand when working on
Popoveris the difference between:Popovercomponent)List of changes:
fallbackReferenceElementand thereferenceOwnerDocument. This is to ensure reactive updates when any of those variables change (as suggested in the docs)referenceOwnerDocumentand of thereferenceelement under the sameuseLayoutEffectcall. This ensures that these two updates happen together. The dependency list of theuseLayoutEffectcall has also been updated to include all possible permutations ofanchorRef. Finally, the code calculating these two values has been moved to a separate file, in order to make the code in thePopovershorter and easier to follow.autoUpdatecall from theuseLayoutEffecthook to thewhileElementsMountedoption of theuseFloatinghook. TheautoUpdatecan be an expensive function to call, and instead of calling it explicitly in theuseLayoutEffecthook, we should letfloating-uidecide when to call it (this follows the suggestion from the docs)arrowmiddleware. The middleware is not added conditionally (as it already does that internally, based on the value of the arrowelement), and the arrow ref is now a callback ref which callsupdate(), thus making sure that the popover's arrow is always positioned correctly. (as explained in the docs)framer-motionto animate the popover towards its new placement, which would throw offfloating-ui's measurements / calculations.Testing Instructions
In Storybook
offset,hasArrow,placement...) and make sure that the popover on screen updates correctlyWithSlotOutsideIframefinally aligns correctly to its anchor inside the iframeIn the Editor
trunkbehaviorScreenshots or screencast
Storybook - default story
trunk(notice how the popover's position is not correct when changingplacement)popover-trunk.mp4
This PR:
popover-pr.mp4
Storybook - iframe story
trunk(notice how the popover is not positioned correctly with respect to its anchor in the iframe)popover-iframe-trunk.mp4
This PR:
popover-iframe-pr.mp4