From 120fc62a2dc10f460016ae7de08af0f00c0a4c8c Mon Sep 17 00:00:00 2001 From: beefchimi Date: Wed, 11 Aug 2021 11:38:53 -0400 Subject: [PATCH 1/6] :alembic: [Popover] Expose imperative relayout function --- src/components/Popover/Popover.tsx | 77 ++++++++++++++----- .../PopoverOverlay/PopoverOverlay.tsx | 14 ++++ .../PositionedOverlay/PositionedOverlay.tsx | 5 ++ src/components/index.ts | 6 +- 4 files changed, 83 insertions(+), 19 deletions(-) diff --git a/src/components/Popover/Popover.tsx b/src/components/Popover/Popover.tsx index c3106304ccc..df398474ab9 100644 --- a/src/components/Popover/Popover.tsx +++ b/src/components/Popover/Popover.tsx @@ -1,11 +1,13 @@ import React, { Children, - useRef, + forwardRef, useEffect, useCallback, + useImperativeHandle, + useRef, useState, - AriaAttributes, } from 'react'; +import type {AriaAttributes} from 'react'; import { findFirstFocusableNodeIncludingDisabled, @@ -83,28 +85,66 @@ export interface PopoverProps { // Letting this be implicit works in this project but fails in projects that use // generated *.d.ts files. -export const Popover: React.FunctionComponent & { +/* +type PopoverComponentType = React.FunctionComponent & { Pane: typeof Pane; Section: typeof Section; -} = function Popover({ - activatorWrapper = 'div', - children, - onClose, - activator, - preventFocusOnClose, - active, - fixed, - ariaHaspopup, - preferInputActivator = true, - colorScheme, - zIndexOverride, - ...rest -}: PopoverProps) { +}; +*/ + +export interface PopoverHandles { + forceReLayout(): void; +} + +interface PopoverSubcomponents { + // TODO: How can we make these required props? + Pane?: typeof Pane; + Section?: typeof Section; +} + +type PopoverComponentType = React.ForwardRefExoticComponent< + PopoverProps & React.RefAttributes +> & + PopoverSubcomponents; + +export const Popover: PopoverComponentType = forwardRef(function Popover( + { + activatorWrapper = 'div', + children, + onClose, + activator, + preventFocusOnClose, + active, + fixed, + ariaHaspopup, + preferInputActivator = true, + colorScheme, + zIndexOverride, + ...rest + }: PopoverProps, + ref, +) { const [activatorNode, setActivatorNode] = useState(); const activatorContainer = useRef(null); const WrapperComponent: any = activatorWrapper; const id = useUniqueId('popover'); + const overlayRef = useRef(null); + + function forceReLayout() { + requestAnimationFrame(() => { + console.log(`Popover forceReLayout: ${id}`, ref); + console.log('Popover > overlayRef', overlayRef); + overlayRef.current?.forceReLayout(); + }); + } + + useImperativeHandle(ref, () => { + return { + forceReLayout, + }; + }); + const setAccessibilityAttributes = useCallback(() => { if (activatorContainer.current == null) { return; @@ -178,6 +218,7 @@ export const Popover: React.FunctionComponent & { const portal = activatorNode ? ( & { {portal} ); -}; +}); function isInPortal(element: Element) { let parentElement = element.parentElement; diff --git a/src/components/Popover/components/PopoverOverlay/PopoverOverlay.tsx b/src/components/Popover/components/PopoverOverlay/PopoverOverlay.tsx index f97e9539476..3e2f418a622 100644 --- a/src/components/Popover/components/PopoverOverlay/PopoverOverlay.tsx +++ b/src/components/Popover/components/PopoverOverlay/PopoverOverlay.tsx @@ -69,6 +69,19 @@ export class PopoverOverlay extends PureComponent { private contentNode = createRef(); private enteringTimer?: number; private exitingTimer?: number; + private overlayRef: React.RefObject; + + constructor(props: PopoverOverlayProps) { + super(props); + this.overlayRef = createRef(); + } + + forceReLayout() { + requestAnimationFrame(() => { + console.log('PopoverOverlay > overlayRef', this.overlayRef.current); + this.overlayRef.current?.forceReLayout(); + }); + } changeTransitionStatus(transitionStatus: TransitionStatus, cb?: () => void) { this.setState({transitionStatus}, cb); @@ -136,6 +149,7 @@ export class PopoverOverlay extends PureComponent { return ( forceReLayout'); + requestAnimationFrame(() => this.handleMeasurement()); + } + private overlayDetails = (): OverlayDetails => { const { measuring, diff --git a/src/components/index.ts b/src/components/index.ts index 5d14b8e5200..3e7cc73ab53 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -205,7 +205,11 @@ export {PolarisTestProvider} from './PolarisTestProvider'; export type {WithPolarisTestProviderOptions} from './PolarisTestProvider'; export {Popover, PopoverCloseSource} from './Popover'; -export type {PopoverProps, PopoverAutofocusTarget} from './Popover'; +export type { + PopoverProps, + PopoverAutofocusTarget, + PopoverHandles, +} from './Popover'; export {Portal} from './Portal'; export type {PortalProps} from './Portal'; From 4bdd457f55188e079618592f832ce49f76b96332 Mon Sep 17 00:00:00 2001 From: beefchimi Date: Thu, 12 Aug 2021 13:52:44 -0400 Subject: [PATCH 2/6] :art: [Popover] Code cleanup / limit to one rAF --- src/components/Popover/Popover.tsx | 18 ++++-------------- .../PopoverOverlay/PopoverOverlay.tsx | 5 +---- .../PositionedOverlay/PositionedOverlay.tsx | 5 ++++- 3 files changed, 9 insertions(+), 19 deletions(-) diff --git a/src/components/Popover/Popover.tsx b/src/components/Popover/Popover.tsx index df398474ab9..9b7c11591fa 100644 --- a/src/components/Popover/Popover.tsx +++ b/src/components/Popover/Popover.tsx @@ -85,13 +85,6 @@ export interface PopoverProps { // Letting this be implicit works in this project but fails in projects that use // generated *.d.ts files. -/* -type PopoverComponentType = React.FunctionComponent & { - Pane: typeof Pane; - Section: typeof Section; -}; -*/ - export interface PopoverHandles { forceReLayout(): void; } @@ -125,18 +118,15 @@ export const Popover: PopoverComponentType = forwardRef(function Popover( ref, ) { const [activatorNode, setActivatorNode] = useState(); + + const overlayRef = useRef(null); const activatorContainer = useRef(null); + const WrapperComponent: any = activatorWrapper; const id = useUniqueId('popover'); - const overlayRef = useRef(null); - function forceReLayout() { - requestAnimationFrame(() => { - console.log(`Popover forceReLayout: ${id}`, ref); - console.log('Popover > overlayRef', overlayRef); - overlayRef.current?.forceReLayout(); - }); + overlayRef.current?.forceReLayout(); } useImperativeHandle(ref, () => { diff --git a/src/components/Popover/components/PopoverOverlay/PopoverOverlay.tsx b/src/components/Popover/components/PopoverOverlay/PopoverOverlay.tsx index 3e2f418a622..71dc4f65b74 100644 --- a/src/components/Popover/components/PopoverOverlay/PopoverOverlay.tsx +++ b/src/components/Popover/components/PopoverOverlay/PopoverOverlay.tsx @@ -77,10 +77,7 @@ export class PopoverOverlay extends PureComponent { } forceReLayout() { - requestAnimationFrame(() => { - console.log('PopoverOverlay > overlayRef', this.overlayRef.current); - this.overlayRef.current?.forceReLayout(); - }); + this.overlayRef.current?.forceReLayout(); } changeTransitionStatus(transitionStatus: TransitionStatus, cb?: () => void) { diff --git a/src/components/PositionedOverlay/PositionedOverlay.tsx b/src/components/PositionedOverlay/PositionedOverlay.tsx index 47bbbcc29c1..52cffadd81f 100644 --- a/src/components/PositionedOverlay/PositionedOverlay.tsx +++ b/src/components/PositionedOverlay/PositionedOverlay.tsx @@ -159,7 +159,10 @@ export class PositionedOverlay extends PureComponent< } forceReLayout() { - console.log('PositionedOverlay > forceReLayout'); + // Wait a single animation frame before re-measuring. + // Consumer's may also need to setup their own timers for + // triggering forceReLayout() `children` use animation. + // Ideally, forceReLayout() is fired at the end of a transition event. requestAnimationFrame(() => this.handleMeasurement()); } From 10e067536fd91f9ad6775f8c9b648389ec0e27d5 Mon Sep 17 00:00:00 2001 From: beefchimi Date: Thu, 12 Aug 2021 14:56:13 -0400 Subject: [PATCH 3/6] :construction_worker: [Popover] Update tests --- .../tests/PopoverOverlay.test.tsx | 28 ++++++++++++++++- src/components/Popover/tests/Popover.test.tsx | 30 ++++++++++++++++++- .../tests/PositionedOverlay.test.tsx | 19 +++++++++++- 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/src/components/Popover/components/PopoverOverlay/tests/PopoverOverlay.test.tsx b/src/components/Popover/components/PopoverOverlay/tests/PopoverOverlay.test.tsx index 34255fe5b3e..517592c3db7 100644 --- a/src/components/Popover/components/PopoverOverlay/tests/PopoverOverlay.test.tsx +++ b/src/components/Popover/components/PopoverOverlay/tests/PopoverOverlay.test.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useRef} from 'react'; // eslint-disable-next-line no-restricted-imports import { mountWithAppProvider, @@ -447,6 +447,32 @@ describe('', () => { expect(document.activeElement).not.toBe(focusTargetFirstNode); }); }); + + describe('forceReLayout', () => { + it('exposes a function that allows the Overlay to be programmatically re-rendered', () => { + let overlayRef = null; + + function Test() { + overlayRef = useRef(null); + + return ( + + + + ); + } + + mountWithApp(); + + expect(overlayRef).toHaveProperty('current.forceReLayout'); + }); + }); }); function noop() {} diff --git a/src/components/Popover/tests/Popover.test.tsx b/src/components/Popover/tests/Popover.test.tsx index 3787bb1b1eb..91458d3040a 100644 --- a/src/components/Popover/tests/Popover.test.tsx +++ b/src/components/Popover/tests/Popover.test.tsx @@ -1,9 +1,10 @@ -import React, {useState, useCallback} from 'react'; +import React, {useCallback, useRef, useState} from 'react'; import {mountWithApp} from 'test-utilities'; import {PositionedOverlay} from 'components/PositionedOverlay'; import {Portal} from 'components'; import {Popover} from '../Popover'; +import type {PopoverHandles} from '../Popover'; import {PopoverOverlay} from '../components'; import * as setActivatorAttributes from '../set-activator-attributes'; @@ -343,6 +344,33 @@ describe('', () => { expect(document.activeElement).not.toBe(activatorTarget); expect(document.activeElement).not.toBe(nextElementTarget); }); + + describe('forceReLayout', () => { + it('exposes a function that allows the Overlay to be programmatically re-rendered', () => { + let popoverRef: React.RefObject | null = null; + + function Test() { + popoverRef = useRef(null); + + return ( + Activator} + onClose={spy} + /> + ); + } + + mountWithApp(); + + expect(popoverRef).toStrictEqual({ + current: { + forceReLayout: expect.anything(), + }, + }); + }); + }); }); function noop() {} diff --git a/src/components/PositionedOverlay/tests/PositionedOverlay.test.tsx b/src/components/PositionedOverlay/tests/PositionedOverlay.test.tsx index 1bd293a64b3..d74a81991aa 100644 --- a/src/components/PositionedOverlay/tests/PositionedOverlay.test.tsx +++ b/src/components/PositionedOverlay/tests/PositionedOverlay.test.tsx @@ -1,6 +1,7 @@ -import React from 'react'; +import React, {useRef} from 'react'; // eslint-disable-next-line no-restricted-imports import {mountWithAppProvider} from 'test-utilities/legacy'; +import {mountWithApp} from 'test-utilities/react-testing'; import {EventListener} from '../../EventListener'; import {PositionedOverlay} from '../PositionedOverlay'; @@ -275,6 +276,22 @@ describe('', () => { ).toBe(false); }); }); + + describe('forceReLayout', () => { + it('exposes a function that allows the Overlay to be programmatically re-rendered', () => { + let overlayRef = null; + + function Test() { + overlayRef = useRef(null); + + return ; + } + + mountWithApp(); + + expect(overlayRef).toHaveProperty('current.forceReLayout'); + }); + }); }); function mockRender() { From a65388bad060d70b4101c02da08bf7ac97f3387d Mon Sep 17 00:00:00 2001 From: beefchimi Date: Thu, 12 Aug 2021 14:59:06 -0400 Subject: [PATCH 4/6] :pencil2: [UNRELEASED] Add notes --- UNRELEASED.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/UNRELEASED.md b/UNRELEASED.md index 98fd56384c5..f1ae8e6c5c8 100644 --- a/UNRELEASED.md +++ b/UNRELEASED.md @@ -15,6 +15,8 @@ Use [the changelog guidelines](https://git.io/polaris-changelog-guidelines) to f - Allow promoted actions to be rendered as a menu on the `BulkAction` component ([#4266](https://github.com/Shopify/polaris-react/pull/4266)) - Add `extraSmall` prop to `Avatar` ([#4371](https://github.com/Shopify/polaris-react/pull/4371)) - Add `critical` color option to `ProgressBar` component ([#4408](https://github.com/Shopify/polaris-react/pull/4408)) +- `Popover` now exposes an imperative `forceReLayout()` API for programmatically triggering a re-render of the underlying overlay component ([#4385](https://github.com/Shopify/polaris-react/pull/4385)) +- `PositionedOverlay` now exposes an imperative `forceReLayout()` API for programmatically triggering a re-render of the component ([#4385](https://github.com/Shopify/polaris-react/pull/4385)) ### Bug fixes From f304a48343b01c20469ddefbeca7777adc091662 Mon Sep 17 00:00:00 2001 From: beefchimi Date: Tue, 17 Aug 2021 09:05:10 -0400 Subject: [PATCH 5/6] :white_check_mark: [Review] Improve Popover typing and export --- src/components/Popover/Popover.tsx | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/components/Popover/Popover.tsx b/src/components/Popover/Popover.tsx index 9b7c11591fa..2fbca6d055c 100644 --- a/src/components/Popover/Popover.tsx +++ b/src/components/Popover/Popover.tsx @@ -89,18 +89,11 @@ export interface PopoverHandles { forceReLayout(): void; } -interface PopoverSubcomponents { - // TODO: How can we make these required props? - Pane?: typeof Pane; - Section?: typeof Section; -} - type PopoverComponentType = React.ForwardRefExoticComponent< PopoverProps & React.RefAttributes -> & - PopoverSubcomponents; +>; -export const Popover: PopoverComponentType = forwardRef(function Popover( +const PopoverComponent: PopoverComponentType = forwardRef(function Popover( { activatorWrapper = 'div', children, @@ -243,5 +236,4 @@ function isInPortal(element: Element) { return true; } -Popover.Pane = Pane; -Popover.Section = Section; +export const Popover = Object.assign(PopoverComponent, {Pane, Section}); From e96b2bfd9690878d119a644266e66daae8a6a61e Mon Sep 17 00:00:00 2001 From: beefchimi Date: Tue, 17 Aug 2021 09:21:31 -0400 Subject: [PATCH 6/6] :white_check_mark: [Review] Rename some types --- UNRELEASED.md | 2 + src/components/Popover/Popover.tsx | 261 +++++++++--------- .../PopoverOverlay/PopoverOverlay.tsx | 4 +- .../tests/PopoverOverlay.test.tsx | 4 +- src/components/Popover/tests/Popover.test.tsx | 8 +- .../PositionedOverlay/PositionedOverlay.tsx | 8 +- .../tests/PositionedOverlay.test.tsx | 4 +- src/components/index.ts | 2 +- 8 files changed, 147 insertions(+), 146 deletions(-) diff --git a/UNRELEASED.md b/UNRELEASED.md index f1ae8e6c5c8..fe7d5c52392 100644 --- a/UNRELEASED.md +++ b/UNRELEASED.md @@ -17,6 +17,8 @@ Use [the changelog guidelines](https://git.io/polaris-changelog-guidelines) to f - Add `critical` color option to `ProgressBar` component ([#4408](https://github.com/Shopify/polaris-react/pull/4408)) - `Popover` now exposes an imperative `forceReLayout()` API for programmatically triggering a re-render of the underlying overlay component ([#4385](https://github.com/Shopify/polaris-react/pull/4385)) - `PositionedOverlay` now exposes an imperative `forceReLayout()` API for programmatically triggering a re-render of the component ([#4385](https://github.com/Shopify/polaris-react/pull/4385)) +- `Popover` now exposes an imperative `forceUpdatePosition()` API for programmatically triggering a re-render of the underlying overlay component ([#4385](https://github.com/Shopify/polaris-react/pull/4385)) +- `PositionedOverlay` now exposes an imperative `forceUpdatePosition()` API for programmatically triggering a re-render of the component ([#4385](https://github.com/Shopify/polaris-react/pull/4385)) ### Bug fixes diff --git a/src/components/Popover/Popover.tsx b/src/components/Popover/Popover.tsx index 2fbca6d055c..05f9838c792 100644 --- a/src/components/Popover/Popover.tsx +++ b/src/components/Popover/Popover.tsx @@ -80,150 +80,149 @@ export interface PopoverProps { autofocusTarget?: PopoverAutofocusTarget; } +export interface PopoverPublicAPI { + forceUpdatePosition(): void; +} + // TypeScript can't generate types that correctly infer the typing of // subcomponents so explicitly state the subcomponents in the type definition. // Letting this be implicit works in this project but fails in projects that use // generated *.d.ts files. -export interface PopoverHandles { - forceReLayout(): void; -} - -type PopoverComponentType = React.ForwardRefExoticComponent< - PopoverProps & React.RefAttributes ->; - -const PopoverComponent: PopoverComponentType = forwardRef(function Popover( - { - activatorWrapper = 'div', - children, - onClose, - activator, - preventFocusOnClose, - active, - fixed, - ariaHaspopup, - preferInputActivator = true, - colorScheme, - zIndexOverride, - ...rest - }: PopoverProps, - ref, -) { - const [activatorNode, setActivatorNode] = useState(); - - const overlayRef = useRef(null); - const activatorContainer = useRef(null); - - const WrapperComponent: any = activatorWrapper; - const id = useUniqueId('popover'); - - function forceReLayout() { - overlayRef.current?.forceReLayout(); - } - - useImperativeHandle(ref, () => { - return { - forceReLayout, - }; - }); - - const setAccessibilityAttributes = useCallback(() => { - if (activatorContainer.current == null) { - return; - } - - const firstFocusable = findFirstFocusableNodeIncludingDisabled( - activatorContainer.current, - ); - const focusableActivator: HTMLElement & { - disabled?: boolean; - } = firstFocusable || activatorContainer.current; - - const activatorDisabled = - 'disabled' in focusableActivator && Boolean(focusableActivator.disabled); - - setActivatorAttributes(focusableActivator, { - id, +const PopoverComponent = forwardRef( + function Popover( + { + activatorWrapper = 'div', + children, + onClose, + activator, + preventFocusOnClose, active, + fixed, ariaHaspopup, - activatorDisabled, - }); - }, [id, active, ariaHaspopup]); - - const handleClose = (source: PopoverCloseSource) => { - onClose(source); - if (activatorContainer.current == null || preventFocusOnClose) { - return; + preferInputActivator = true, + colorScheme, + zIndexOverride, + ...rest + }, + ref, + ) { + const [activatorNode, setActivatorNode] = useState(); + + const overlayRef = useRef(null); + const activatorContainer = useRef(null); + + const WrapperComponent: any = activatorWrapper; + const id = useUniqueId('popover'); + + function forceUpdatePosition() { + overlayRef.current?.forceUpdatePosition(); } - if ( - (source === PopoverCloseSource.FocusOut || - source === PopoverCloseSource.EscapeKeypress) && - activatorNode - ) { - const focusableActivator = - findFirstFocusableNodeIncludingDisabled(activatorNode) || - findFirstFocusableNodeIncludingDisabled(activatorContainer.current) || - activatorContainer.current; - if (!focusNextFocusableNode(focusableActivator, isInPortal)) { - focusableActivator.focus(); + useImperativeHandle(ref, () => { + return { + forceUpdatePosition, + }; + }); + + const setAccessibilityAttributes = useCallback(() => { + if (activatorContainer.current == null) { + return; } - } - }; - useEffect(() => { - if (!activatorNode && activatorContainer.current) { - setActivatorNode( - activatorContainer.current.firstElementChild as HTMLElement, - ); - } else if ( - activatorNode && - activatorContainer.current && - !activatorContainer.current.contains(activatorNode) - ) { - setActivatorNode( - activatorContainer.current.firstElementChild as HTMLElement, + const firstFocusable = findFirstFocusableNodeIncludingDisabled( + activatorContainer.current, ); - } - setAccessibilityAttributes(); - }, [activatorNode, setAccessibilityAttributes]); + const focusableActivator: HTMLElement & { + disabled?: boolean; + } = firstFocusable || activatorContainer.current; + + const activatorDisabled = + 'disabled' in focusableActivator && + Boolean(focusableActivator.disabled); + + setActivatorAttributes(focusableActivator, { + id, + active, + ariaHaspopup, + activatorDisabled, + }); + }, [id, active, ariaHaspopup]); + + const handleClose = (source: PopoverCloseSource) => { + onClose(source); + if (activatorContainer.current == null || preventFocusOnClose) { + return; + } - useEffect(() => { - if (activatorNode && activatorContainer.current) { - setActivatorNode( - activatorContainer.current.firstElementChild as HTMLElement, - ); - } - setAccessibilityAttributes(); - }, [activatorNode, setAccessibilityAttributes]); - - const portal = activatorNode ? ( - - - {children} - - - ) : null; - - return ( - - {Children.only(activator)} - {portal} - - ); -}); + if ( + (source === PopoverCloseSource.FocusOut || + source === PopoverCloseSource.EscapeKeypress) && + activatorNode + ) { + const focusableActivator = + findFirstFocusableNodeIncludingDisabled(activatorNode) || + findFirstFocusableNodeIncludingDisabled(activatorContainer.current) || + activatorContainer.current; + if (!focusNextFocusableNode(focusableActivator, isInPortal)) { + focusableActivator.focus(); + } + } + }; + + useEffect(() => { + if (!activatorNode && activatorContainer.current) { + setActivatorNode( + activatorContainer.current.firstElementChild as HTMLElement, + ); + } else if ( + activatorNode && + activatorContainer.current && + !activatorContainer.current.contains(activatorNode) + ) { + setActivatorNode( + activatorContainer.current.firstElementChild as HTMLElement, + ); + } + setAccessibilityAttributes(); + }, [activatorNode, setAccessibilityAttributes]); + + useEffect(() => { + if (activatorNode && activatorContainer.current) { + setActivatorNode( + activatorContainer.current.firstElementChild as HTMLElement, + ); + } + setAccessibilityAttributes(); + }, [activatorNode, setAccessibilityAttributes]); + + const portal = activatorNode ? ( + + + {children} + + + ) : null; + + return ( + + {Children.only(activator)} + {portal} + + ); + }, +); function isInPortal(element: Element) { let parentElement = element.parentElement; diff --git a/src/components/Popover/components/PopoverOverlay/PopoverOverlay.tsx b/src/components/Popover/components/PopoverOverlay/PopoverOverlay.tsx index 71dc4f65b74..4ea3fb77215 100644 --- a/src/components/Popover/components/PopoverOverlay/PopoverOverlay.tsx +++ b/src/components/Popover/components/PopoverOverlay/PopoverOverlay.tsx @@ -76,8 +76,8 @@ export class PopoverOverlay extends PureComponent { this.overlayRef = createRef(); } - forceReLayout() { - this.overlayRef.current?.forceReLayout(); + forceUpdatePosition() { + this.overlayRef.current?.forceUpdatePosition(); } changeTransitionStatus(transitionStatus: TransitionStatus, cb?: () => void) { diff --git a/src/components/Popover/components/PopoverOverlay/tests/PopoverOverlay.test.tsx b/src/components/Popover/components/PopoverOverlay/tests/PopoverOverlay.test.tsx index 517592c3db7..f8ceb73dca9 100644 --- a/src/components/Popover/components/PopoverOverlay/tests/PopoverOverlay.test.tsx +++ b/src/components/Popover/components/PopoverOverlay/tests/PopoverOverlay.test.tsx @@ -448,7 +448,7 @@ describe('', () => { }); }); - describe('forceReLayout', () => { + describe('forceUpdatePosition', () => { it('exposes a function that allows the Overlay to be programmatically re-rendered', () => { let overlayRef = null; @@ -470,7 +470,7 @@ describe('', () => { mountWithApp(); - expect(overlayRef).toHaveProperty('current.forceReLayout'); + expect(overlayRef).toHaveProperty('current.forceUpdatePosition'); }); }); }); diff --git a/src/components/Popover/tests/Popover.test.tsx b/src/components/Popover/tests/Popover.test.tsx index 91458d3040a..8295e13605b 100644 --- a/src/components/Popover/tests/Popover.test.tsx +++ b/src/components/Popover/tests/Popover.test.tsx @@ -4,7 +4,7 @@ import {PositionedOverlay} from 'components/PositionedOverlay'; import {Portal} from 'components'; import {Popover} from '../Popover'; -import type {PopoverHandles} from '../Popover'; +import type {PopoverPublicAPI} from '../Popover'; import {PopoverOverlay} from '../components'; import * as setActivatorAttributes from '../set-activator-attributes'; @@ -345,9 +345,9 @@ describe('', () => { expect(document.activeElement).not.toBe(nextElementTarget); }); - describe('forceReLayout', () => { + describe('forceUpdatePosition', () => { it('exposes a function that allows the Overlay to be programmatically re-rendered', () => { - let popoverRef: React.RefObject | null = null; + let popoverRef: React.RefObject | null = null; function Test() { popoverRef = useRef(null); @@ -366,7 +366,7 @@ describe('', () => { expect(popoverRef).toStrictEqual({ current: { - forceReLayout: expect.anything(), + forceUpdatePosition: expect.anything(), }, }); }); diff --git a/src/components/PositionedOverlay/PositionedOverlay.tsx b/src/components/PositionedOverlay/PositionedOverlay.tsx index 52cffadd81f..12cf5989e32 100644 --- a/src/components/PositionedOverlay/PositionedOverlay.tsx +++ b/src/components/PositionedOverlay/PositionedOverlay.tsx @@ -158,12 +158,12 @@ export class PositionedOverlay extends PureComponent< ); } - forceReLayout() { + forceUpdatePosition() { // Wait a single animation frame before re-measuring. // Consumer's may also need to setup their own timers for - // triggering forceReLayout() `children` use animation. - // Ideally, forceReLayout() is fired at the end of a transition event. - requestAnimationFrame(() => this.handleMeasurement()); + // triggering forceUpdatePosition() `children` use animation. + // Ideally, forceUpdatePosition() is fired at the end of a transition event. + requestAnimationFrame(this.handleMeasurement); } private overlayDetails = (): OverlayDetails => { diff --git a/src/components/PositionedOverlay/tests/PositionedOverlay.test.tsx b/src/components/PositionedOverlay/tests/PositionedOverlay.test.tsx index d74a81991aa..9795e34c48a 100644 --- a/src/components/PositionedOverlay/tests/PositionedOverlay.test.tsx +++ b/src/components/PositionedOverlay/tests/PositionedOverlay.test.tsx @@ -277,7 +277,7 @@ describe('', () => { }); }); - describe('forceReLayout', () => { + describe('forceUpdatePosition', () => { it('exposes a function that allows the Overlay to be programmatically re-rendered', () => { let overlayRef = null; @@ -289,7 +289,7 @@ describe('', () => { mountWithApp(); - expect(overlayRef).toHaveProperty('current.forceReLayout'); + expect(overlayRef).toHaveProperty('current.forceUpdatePosition'); }); }); }); diff --git a/src/components/index.ts b/src/components/index.ts index 3e7cc73ab53..f86b89e5716 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -208,7 +208,7 @@ export {Popover, PopoverCloseSource} from './Popover'; export type { PopoverProps, PopoverAutofocusTarget, - PopoverHandles, + PopoverPublicAPI, } from './Popover'; export {Portal} from './Portal';