Skip to content

Commit af56de0

Browse files
jabrksLFDanLu
andauthored
fix: Don't close popovers on scroll (#7541)
* fix: Don't add scroll listener to popovers * Remove obsolete code * Consistency * Unnecessary async * Better test * Neatening up --------- Co-authored-by: Daniel Lu <[email protected]>
1 parent c246c2e commit af56de0

File tree

4 files changed

+44
-3
lines changed

4 files changed

+44
-3
lines changed

packages/@react-aria/overlays/src/useCloseOnScroll.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const onCloseMap: WeakMap<Element, () => void> = new WeakMap();
2323
interface CloseOnScrollOptions {
2424
triggerRef: RefObject<Element | null>,
2525
isOpen?: boolean,
26-
onClose?: () => void
26+
onClose?: (() => void) | null
2727
}
2828

2929
/** @private */

packages/@react-aria/overlays/src/useOverlayPosition.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export interface AriaPositionProps extends PositionProps {
4848
*/
4949
shouldUpdatePosition?: boolean,
5050
/** Handler that is called when the overlay should close. */
51-
onClose?: () => void,
51+
onClose?: (() => void) | null,
5252
/**
5353
* The maxHeight specified for the overlay element.
5454
* By default, it will take all space up to the current viewport height.

packages/@react-aria/overlays/src/usePopover.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ export function usePopover(props: AriaPopoverProps, state: OverlayTriggerState):
9898
targetRef: triggerRef,
9999
overlayRef: popoverRef,
100100
isOpen: state.isOpen,
101-
onClose: isNonModal ? state.close : undefined
101+
onClose: isNonModal ? state.close : null
102102
});
103103

104104
usePreventScroll({
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright 2024 Adobe. All rights reserved.
3+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License. You may obtain a copy
5+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
*
7+
* Unless required by applicable law or agreed to in writing, software distributed under
8+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9+
* OF ANY KIND, either express or implied. See the License for the specific language
10+
* governing permissions and limitations under the License.
11+
*/
12+
13+
import {fireEvent, render} from '@react-spectrum/test-utils-internal';
14+
import {type OverlayTriggerProps, useOverlayTriggerState} from '@react-stately/overlays';
15+
import React, {useRef} from 'react';
16+
import {useOverlayTrigger, usePopover} from '../';
17+
18+
function Example(props: OverlayTriggerProps) {
19+
const triggerRef = useRef(null);
20+
const popoverRef = useRef(null);
21+
const state = useOverlayTriggerState(props);
22+
useOverlayTrigger({type: 'listbox'}, state, triggerRef);
23+
const {popoverProps} = usePopover({triggerRef, popoverRef}, state);
24+
25+
return (
26+
<div>
27+
<div ref={triggerRef} />
28+
<div {...popoverProps} ref={popoverRef} />
29+
</div>
30+
);
31+
}
32+
33+
describe('usePopover', () => {
34+
it('should not close popover on scroll', () => {
35+
const onOpenChange = jest.fn();
36+
render(<Example isOpen onOpenChange={onOpenChange} />);
37+
38+
fireEvent.scroll(document.body);
39+
expect(onOpenChange).not.toHaveBeenCalled();
40+
});
41+
});

0 commit comments

Comments
 (0)