@@ -25,27 +25,34 @@ type PopoverCSSProps =
2525 | 'bottom'
2626 | 'marginTop' ;
2727
28+ type PopoverPositioningOptions = {
29+ open : boolean ;
30+ placement : 'above' | 'below' ;
31+
32+ /**
33+ * Whether the popover should be aligned to the right side of the anchor
34+ * element or not
35+ */
36+ alignToRight : boolean ;
37+
38+ /** Native popover API is used to toggle the popover */
39+ asNativePopover : boolean ;
40+ } ;
41+
2842/**
2943 * Manages the popover position manually to make sure it renders "next" to the
3044 * anchor element (above or below). This is mainly needed when using the
3145 * popover API, as that makes it render in the top layer, making it impossible
3246 * to position it relative to the anchor element via regular CSS.
33- *
34- * @param asNativePopover - Native popover API is used to toggle the popover
35- * @param alignToRight - Whether the popover should be aligned to the right side
36- * of the anchor element or not
3747 */
3848function usePopoverPositioning (
39- anchorElementRef : RefObject < HTMLElement | undefined > ,
4049 popoverRef : RefObject < HTMLElement | undefined > ,
41- popoverOpen : boolean ,
42- asNativePopover : boolean ,
43- alignToRight : boolean ,
44- placement : 'above' | 'below' ,
50+ anchorRef : RefObject < HTMLElement | undefined > ,
51+ { open, asNativePopover, alignToRight, placement } : PopoverPositioningOptions ,
4552) {
4653 const adjustPopoverPositioning = useCallback ( ( ) => {
4754 const popoverEl = popoverRef . current ! ;
48- const anchorEl = anchorElementRef . current ! ;
55+ const anchorEl = anchorRef . current ! ;
4956
5057 /**
5158 * Set the positioning styles synchronously (not via <div style={computedStyles} />),
@@ -131,10 +138,10 @@ function usePopoverPositioning(
131138 : `calc(${ absBodyTop + anchorElDistanceToTop + anchorElHeight } px + ${ POPOVER_ANCHOR_EL_GAP } )` ,
132139 left : `${ Math . max ( POPOVER_VIEWPORT_HORIZONTAL_GAP , left ) } px` ,
133140 } ) ;
134- } , [ asNativePopover , anchorElementRef , popoverRef , alignToRight , placement ] ) ;
141+ } , [ asNativePopover , anchorRef , popoverRef , alignToRight , placement ] ) ;
135142
136143 useLayoutEffect ( ( ) => {
137- if ( ! popoverOpen ) {
144+ if ( ! open ) {
138145 return ( ) => { } ;
139146 }
140147
@@ -171,7 +178,7 @@ function usePopoverPositioning(
171178 listeners . removeAll ( ) ;
172179 observer . disconnect ( ) ;
173180 } ;
174- } , [ adjustPopoverPositioning , asNativePopover , popoverOpen , popoverRef ] ) ;
181+ } , [ adjustPopoverPositioning , asNativePopover , open , popoverRef ] ) ;
175182}
176183
177184/**
@@ -355,14 +362,12 @@ export default function Popover({
355362} : PopoverProps ) {
356363 const popoverRef = useSyncedRef < HTMLElement > ( elementRef ) ;
357364
358- usePopoverPositioning (
359- anchorElementRef ,
360- popoverRef ,
365+ usePopoverPositioning ( popoverRef , anchorElementRef , {
361366 open,
362- asNativePopover ,
363- align === 'right' ,
364367 placement,
365- ) ;
368+ alignToRight : align === 'right' ,
369+ asNativePopover,
370+ } ) ;
366371 useOnClose ( popoverRef , anchorElementRef , onClose , open , asNativePopover ) ;
367372 useRestoreFocusOnClose ( {
368373 open,
0 commit comments