Skip to content

Commit

Permalink
[NOJIRA][BpkPopover] Fix Popover issue that floating-ui's useClick do…
Browse files Browse the repository at this point in the history
…es not support stopPropagation (#3495)

[NOJIRA][BpkPopover] Fix Popover issue that floating-ui's useClick does not support stopPropagation (#3495)

* fix: Popover cannot support and trigger target own event
* fix: resolve floating-ui useClick doesn't support stopPropagation
* fix: abstract target click and referenceProps
* fix: abstract target click and referenceProps
* fix:An update to BpkPopover inside a test was not wrapped in act(...)
* fix: resolve act issue
* fix: resolve act issue
---------

Co-authored-by: Ryan Ruan <[email protected]>
  • Loading branch information
yifeng-ruan and Ryan Ruan authored Jun 17, 2024
1 parent c0154ac commit 850874a
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 3 deletions.
38 changes: 37 additions & 1 deletion packages/bpk-component-popover/src/BpkPopover-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* limitations under the License.
*/

import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { render, screen, fireEvent, waitFor, act } from '@testing-library/react';
import '@testing-library/jest-dom';

import BpkPopover from './BpkPopover';
Expand Down Expand Up @@ -191,4 +191,40 @@ describe('BpkPopover', () => {
expect(onCloseSpy).toHaveBeenCalled();
});
});

it('should call target onClick handler and execute code after stopPropagation', async () => {
const handleClick = jest.fn((event) => {
event.stopPropagation();
// eslint-disable-next-line no-param-reassign
event.afterStopPropagation = true;
});

const { getByRole } = render(
<BpkPopover
id="my-popover"
onClose={jest.fn()}
label="My popover"
closeButtonLabel="Close"
labelAsTitle
closeButtonIcon
target={<button onClick={handleClick} type="button">My target</button>}
isOpen
>
My popover content
</BpkPopover>,
);

const button = getByRole('button', { name: 'My target' });

const event = new MouseEvent('click', { bubbles: true });
jest.spyOn(event, 'stopPropagation');

await waitFor(async () => {
await fireEvent(button, event);
expect(handleClick).toHaveBeenCalled();
expect(event.stopPropagation).toHaveBeenCalled();
expect(handleClick.mock.calls[0][0].afterStopPropagation).toBe(true);
});
});

});
17 changes: 15 additions & 2 deletions packages/bpk-component-popover/src/BpkPopover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,17 +154,30 @@ const BpkPopover = ({
dismiss,
]);

const targetClick = target.props.onClick;
const referenceProps = getReferenceProps(
{
onClick: (event) => {
if (targetClick) {
event.stopPropagation();
targetClick(event);
}
},
}
)

const targetElement = isValidElement(target) ? (
cloneElement(target, {
...getReferenceProps(),
...referenceProps,
// @ts-ignore - we're adding a popover ref to the target element so we can position the popover relative to it
ref: refs.setReference,
})
) : (
<div ref={refs.setReference} {...getReferenceProps()}>
<div ref={refs.setReference} {...referenceProps}>
{target}
</div>
);

const classNames = getClassName('bpk-popover', className);
const bodyClassNames = getClassName(padded && 'bpk-popover__body--padded');

Expand Down

0 comments on commit 850874a

Please sign in to comment.