-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Popover: make more reactive to prop changes, avoid unnecessary updates #43335
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
@@ -105,3 +105,109 @@ export const getFrameOffset = ( document ) => { | |||
const iframeRect = frameElement.getBoundingClientRect(); | |||
return { x: iframeRect.left, y: iframeRect.top }; | |||
}; | |||
|
|||
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
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 👍
@@ -181,29 +205,6 @@ const Popover = ( | |||
? 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
Popover
to useplacement
instead ofposition
- mark
position
as 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
Popover
internals (especially effect dependencies and forced updates) to make component more reactive to external change, but also to avoid unnecessary updates.Why?
Looking at
Popover
its 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
Popover
is the difference between:Popover
component)List of changes:
fallbackReferenceElement
and thereferenceOwnerDocument
. This is to ensure reactive updates when any of those variables change (as suggested in the docs)referenceOwnerDocument
and of thereference
element under the sameuseLayoutEffect
call. This ensures that these two updates happen together. The dependency list of theuseLayoutEffect
call 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 thePopover
shorter and easier to follow.autoUpdate
call from theuseLayoutEffect
hook to thewhileElementsMounted
option of theuseFloating
hook. TheautoUpdate
can be an expensive function to call, and instead of calling it explicitly in theuseLayoutEffect
hook, we should letfloating-ui
decide when to call it (this follows the suggestion from the docs)arrow
middleware. 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-motion
to 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 correctlyWithSlotOutsideIframe
finally aligns correctly to its anchor inside the iframeIn the Editor
trunk
behaviorScreenshots 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