-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
BorderBoxControl: use Popover's new anchor prop #43789
BorderBoxControl: use Popover's new anchor prop #43789
Conversation
const [ popoverProps, setPopoverProps ] = useState< PopoverPartialProps >(); | ||
const [ popoverAnchor, setPopoverAnchor ] = useState< Element >(); | ||
|
||
const containerRef = useCallback( ( node ) => { | ||
setPopoverAnchor( node ); | ||
}, [] ); | ||
|
||
useEffect( () => { | ||
if ( popoverPlacement ) { | ||
setPopoverProps( { | ||
placement: popoverPlacement, | ||
offset: popoverOffset, | ||
anchorRef: containerRef, | ||
anchor: popoverAnchor, | ||
__unstableShift: true, | ||
} | ||
: undefined; | ||
} ); | ||
} else { | ||
setPopoverProps( undefined ); | ||
} | ||
}, [ popoverPlacement, popoverOffset, popoverAnchor ] ); |
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 changes are in place to make sure that, when the containerRef
is updated, popoverProps
are updated too.
Without it, the ref would be updated after the initial value of popoverProps
was computed, and because of how React refs work, React wouldn't re-render the component — meaning that the anchor
property in popoverProps
would be stale until a re-render would be caused by whatever reason.
placement: popoverPlacement, | ||
offset: popoverOffset, | ||
anchorRef: containerRef, | ||
anchor: popoverAnchor, |
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.
Using anchor
instead of anchorRef
const [ popoverProps, setPopoverProps ] = useState< PopoverPartialProps >(); | ||
const [ popoverAnchor, setPopoverAnchor ] = useState< Element >(); | ||
|
||
const containerRef = useCallback( ( node ) => { | ||
setPopoverAnchor( node ); | ||
}, [] ); | ||
|
||
useEffect( () => { | ||
if ( popoverPlacement ) { | ||
setPopoverProps( { | ||
placement: popoverPlacement, | ||
offset: popoverOffset, | ||
anchorRef: containerRef, | ||
anchor: popoverAnchor, | ||
__unstableShift: true, | ||
} | ||
: undefined; | ||
} ); | ||
} else { | ||
setPopoverProps( undefined ); | ||
} | ||
}, [ popoverPlacement, popoverOffset, popoverAnchor ] ); | ||
|
||
const mergedRef = useMergeRefs( [ containerRef, forwardedRef ] ); |
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.
Same set of changes as in the other component
export type PopoverPartialProps = { | ||
placement?: Placement; | ||
offset?: number; | ||
anchor?: ReferenceType; | ||
__unstableShift?: boolean; | ||
}; |
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 should be removed and replaced with the original PopoverProps
type once we type the component (hopefully soon!)
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.
Working on it #43823
@@ -85,6 +85,7 @@ Default.args = { | |||
width: '1px', | |||
}, | |||
__next36pxDefaultSize: false, | |||
popoverPlacement: 'right-start', |
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 added popoverPlacement
while testing for the stale anchor
value, and decided to keep it for convenience.
But the component's stories definitely need to be rewritten in TypeScript so that they can show all props
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 have it on my radar to rewrite the border control component stories in TypeScript and update them to follow the latest approach and guidelines. Unfortunately, I haven't had the bandwidth in the lead-up to 6.1 but hope to in the not-too-distant future.
}, [] ); | ||
|
||
useEffect( () => { | ||
if ( popoverPlacement ) { |
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.
Side note: I'm not in love with the popoverPlacement
and popoverOffset
props, but these were added as part of #40740 and it's not in the scope of this PR to revisit the APIs of BorderBoxControl
Size Change: +45 B (0%) Total Size: 1.25 MB
ℹ️ View Unchanged
|
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.
Nice work @ciampo ✨
The changes look good and tested well for me.
✅ Popover appears as expected when clicking on color button
✅ Popover position updates appropriately when adjusting popover placement in Storybook
✅ When no popover placement is set color button is used as the anchor
✅ Split controls and their popovers behave consistently with the linked control
✅ Popover placement between this PR and trunk is consistent in the editor
Storybook video
Screen.Recording.2022-09-05.at.7.03.02.pm.mp4
Editor video
Screen.Recording.2022-09-05.at.7.29.10.pm.mp4
P.S. We'll need a changelog 🙂
Thank you for the review, @aaronrobertshaw !
Good call. I'm planning on adding CHANGELOG entries on the base PR before merging to |
* BorderBoxControl: use new `anchor` prop for `Popover` * Make sure anchor value is `undefined` instead of `null`
* BorderBoxControl: use new `anchor` prop for `Popover` * Make sure anchor value is `undefined` instead of `null`
* BorderBoxControl: use new `anchor` prop for `Popover` * Make sure anchor value is `undefined` instead of `null`
* BorderBoxControl: use new `anchor` prop for `Popover` * Make sure anchor value is `undefined` instead of `null`
* BorderBoxControl: use new `anchor` prop for `Popover` * Make sure anchor value is `undefined` instead of `null`
* Popover: add new anchor prop, mark other anchor props as deprecated * Add `anchor` prop to Storybook * Add WP version for deprecated props removal * Do not render fallback anchor if there is already a prop-derived anchor * Block inbetween inserter: use Popover's new anchor prop (#43693) * BlockPopoverInbetween: refactor to use `anchor` prop * Simplify logic, use DOMRect * Add missing hook deps * ListViewDropIndicator: use Popover s new anchor prop (#43694) * Temporarily disable derpecation warnings * Block toolbar: use Popover's new anchor prop (#43692) * Block toolbar: use anchor prop instead of anchorRef.{top,bottom} * Update packages/block-editor/src/components/block-popover/index.js Co-authored-by: Lena Morita <lena@jaguchi.com> Co-authored-by: Lena Morita <lena@jaguchi.com> * Dropdown: use Popover s new anchor prop (#43698) * BlockPopover: prevent error when `selectedElement` is not defined * Try to avoid infinite loop * Update PanelRow docs * Edit navigation menu actions: use Popover s new anchor prop * BorderBoxControl: use Popover's new anchor prop (#43789) * BorderBoxControl: use new `anchor` prop for `Popover` * Make sure anchor value is `undefined` instead of `null` * Image URL Input: use new anchor prop for Popover (#43784) * Image URL Input: use new anchor prop for Popover * Prevent value from being `null` * Edit site Actions: use new anchor prop for Popover (#43810) * Buttons block: use new Popover anchor prop (#43785) * Buttons block: use new `anchor` prop for `Popover` * Prevent anchor value from being `null` * Navigation block: use new anchor prop for Popover (#43786) * Navigation block: use new `anchor` prop for `Popover` * Use anchor for the Navigation submenu block too * Prevent anchor value from being `null` * Post Date block: use new anchor prop for Popover (#43787) * Post Date block: use new `anchor` prop for `Popover` * Prevent anchor value from being `null` * Tooltip: refactor using Popover's new anchor prop (#43799) * Tooltip: use Popover s new anchor prop * Use internal state to force re-renders when the anchor ref changes * Simplify code * Improve docs around using state instead of refs for the anchor element * Allow `anchor` to be `null` * Edit Post: use Popover's new anchor prop (#43808) * Edit Post: use Popover s new anchor prop * Update comment * SImplify code * Update packages/edit-post/src/components/sidebar/post-schedule/index.js Co-authored-by: Daniel Richards <daniel.richards@automattic.com> * Allow passing a `null` anchor Co-authored-by: Daniel Richards <daniel.richards@automattic.com> * Refactor `useAnchorRef` and related components to work with the new Popover `anchor` prop (#43713) * useAnchorRef: return a VirtualElement instead of a range * Update useAnchorRef usage in FormatToolbarContainer, use anchor prop * Update remaining `useAnchorRef` usages, switch to the `anchor` prop * useAnchorRef: normalize `null` returns to `undefined` as it is not a valid `anchor` value * Revert changes to native RichText component * Update docs * Allow useAnchorRef to return `null` * Re-enable deprecation warnings * Remove fall back to `undefined` from `null` * Ensure reactive updates when the popover anchor updates * Refactor SocialLinkEdit component to use `anchor` instead of `anchorRef` * CHANGELOG * Add new `useAnchor` hook instead of changing existing `useAnchorRef` hook * Fix API docs * Update Popover unit tests * Remove unused import * Use DOMRect in the DomRectWithOwnerDocument type * Improve the wording of deprecation warnings * Put more emphasis on storing anchor in local state Co-authored-by: Lena Morita <lena@jaguchi.com> Co-authored-by: Daniel Richards <daniel.richards@automattic.com>
* Popover: add new anchor prop, mark other anchor props as deprecated * Add `anchor` prop to Storybook * Add WP version for deprecated props removal * Do not render fallback anchor if there is already a prop-derived anchor * Block inbetween inserter: use Popover's new anchor prop (#43693) * BlockPopoverInbetween: refactor to use `anchor` prop * Simplify logic, use DOMRect * Add missing hook deps * ListViewDropIndicator: use Popover s new anchor prop (#43694) * Temporarily disable derpecation warnings * Block toolbar: use Popover's new anchor prop (#43692) * Block toolbar: use anchor prop instead of anchorRef.{top,bottom} * Update packages/block-editor/src/components/block-popover/index.js Co-authored-by: Lena Morita <lena@jaguchi.com> Co-authored-by: Lena Morita <lena@jaguchi.com> * Dropdown: use Popover s new anchor prop (#43698) * BlockPopover: prevent error when `selectedElement` is not defined * Try to avoid infinite loop * Update PanelRow docs * Edit navigation menu actions: use Popover s new anchor prop * BorderBoxControl: use Popover's new anchor prop (#43789) * BorderBoxControl: use new `anchor` prop for `Popover` * Make sure anchor value is `undefined` instead of `null` * Image URL Input: use new anchor prop for Popover (#43784) * Image URL Input: use new anchor prop for Popover * Prevent value from being `null` * Edit site Actions: use new anchor prop for Popover (#43810) * Buttons block: use new Popover anchor prop (#43785) * Buttons block: use new `anchor` prop for `Popover` * Prevent anchor value from being `null` * Navigation block: use new anchor prop for Popover (#43786) * Navigation block: use new `anchor` prop for `Popover` * Use anchor for the Navigation submenu block too * Prevent anchor value from being `null` * Post Date block: use new anchor prop for Popover (#43787) * Post Date block: use new `anchor` prop for `Popover` * Prevent anchor value from being `null` * Tooltip: refactor using Popover's new anchor prop (#43799) * Tooltip: use Popover s new anchor prop * Use internal state to force re-renders when the anchor ref changes * Simplify code * Improve docs around using state instead of refs for the anchor element * Allow `anchor` to be `null` * Edit Post: use Popover's new anchor prop (#43808) * Edit Post: use Popover s new anchor prop * Update comment * SImplify code * Update packages/edit-post/src/components/sidebar/post-schedule/index.js Co-authored-by: Daniel Richards <daniel.richards@automattic.com> * Allow passing a `null` anchor Co-authored-by: Daniel Richards <daniel.richards@automattic.com> * Refactor `useAnchorRef` and related components to work with the new Popover `anchor` prop (#43713) * useAnchorRef: return a VirtualElement instead of a range * Update useAnchorRef usage in FormatToolbarContainer, use anchor prop * Update remaining `useAnchorRef` usages, switch to the `anchor` prop * useAnchorRef: normalize `null` returns to `undefined` as it is not a valid `anchor` value * Revert changes to native RichText component * Update docs * Allow useAnchorRef to return `null` * Re-enable deprecation warnings * Remove fall back to `undefined` from `null` * Ensure reactive updates when the popover anchor updates * Refactor SocialLinkEdit component to use `anchor` instead of `anchorRef` * CHANGELOG * Add new `useAnchor` hook instead of changing existing `useAnchorRef` hook * Fix API docs * Update Popover unit tests * Remove unused import * Use DOMRect in the DomRectWithOwnerDocument type * Improve the wording of deprecation warnings * Put more emphasis on storing anchor in local state Co-authored-by: Lena Morita <lena@jaguchi.com> Co-authored-by: Daniel Richards <daniel.richards@automattic.com>
What?
Refactor the way the
BorderBoxControl
component passes an anchor to Popover, using the newanchor
propWhy?
See #43691 for more context
How?
anchorRef
withanchor
Testing Instructions
In Storybook:
Open the
BorderBoxControl
component and:popoverPlacement
prop and make sure that the popover's position updates as expected when changing that proppopoverPlacement
is set, the popover uses the control group as its anchorpopoverPlacement
is not set, the popover uses the icon button as its anchorpopoverPlacement
is set, the popover uses the control group as its anchorpopoverPlacement
is not set, the popover uses each individual icon button as its anchorIn the editor:
BorderBoxControl
componenttrunk
border-box-control.mp4