diff --git a/.changeset/slow-paws-punch.md b/.changeset/slow-paws-punch.md
new file mode 100644
index 0000000000..8bffd71505
--- /dev/null
+++ b/.changeset/slow-paws-punch.md
@@ -0,0 +1,5 @@
+---
+"@nextui-org/popover": minor
+---
+
+added `shouldCloseOnScroll` to control the popover closing on scroll (#3594)
diff --git a/apps/docs/content/docs/components/popover.mdx b/apps/docs/content/docs/components/popover.mdx
index 9dfa13102d..5576df40db 100644
--- a/apps/docs/content/docs/components/popover.mdx
+++ b/apps/docs/content/docs/components/popover.mdx
@@ -167,7 +167,8 @@ You can customize the `Popover` component by passing custom Tailwind CSS classes
| showArrow | `boolean` | Whether the popover should have an arrow. | `false` |
| shouldFlip | `boolean` | Whether the popover should change its placement and flip when it's about to overflow its boundary area. | `true` |
| triggerScaleOnOpen | `boolean` | Whether the trigger should scale down when the popover is open. | `true` |
-| shouldBlockScroll | `boolean` | Whether to block scrolling outside the popover. | `false` |
+| shouldBlockScroll | `boolean` | Whether the popover should block the scroll outside the popover. | `true` |
+| shouldCloseOnScroll | `boolean` | Wheather the popover should close on scroll | `false` |
| isKeyboardDismissDisabled | `boolean` | Whether pressing the escape key to close the popover should be disabled. | `false` |
| shouldCloseOnBlur | `boolean` | Whether the popover should close when focus is lost or moves outside it. | `false` |
| motionProps | [MotionProps](#motion-props) | The props to modify the framer motion animation. Use the `variants` API to create your own animation. | |
diff --git a/packages/components/popover/__tests__/popover.test.tsx b/packages/components/popover/__tests__/popover.test.tsx
index a73021d666..0f443d4db3 100644
--- a/packages/components/popover/__tests__/popover.test.tsx
+++ b/packages/components/popover/__tests__/popover.test.tsx
@@ -348,3 +348,36 @@ describe("Popover", () => {
expect(popover).toHaveAttribute("aria-expanded", "false");
});
});
+
+it("should close popover on scroll when shouldCloseOnScroll is false", async () => {
+ const wrapper = render(
+
+
+
+
+
+
+
+ ,
+ );
+
+ const popover = wrapper.getByTestId("popover");
+
+ // open popover
+ await act(async () => {
+ await userEvent.click(popover);
+ });
+
+ // assert that the popover is open
+ expect(popover).toHaveAttribute("aria-expanded", "true");
+
+ // scroll it
+ fireEvent.scroll(document.body);
+
+ // assert that the popover is still open
+ expect(popover).toHaveAttribute("aria-expanded", "true");
+});
diff --git a/packages/components/popover/src/use-aria-popover.ts b/packages/components/popover/src/use-aria-popover.ts
index d8f1c78067..1b9cb8d485 100644
--- a/packages/components/popover/src/use-aria-popover.ts
+++ b/packages/components/popover/src/use-aria-popover.ts
@@ -37,6 +37,11 @@ export interface Props {
* @default []
*/
updatePositionDeps?: any[];
+ /**
+ * Whether the popover should close on scroll.
+ * @default true
+ */
+ shouldCloseOnScroll?: boolean;
}
export type ReactAriaPopoverProps = Props & Omit & AriaOverlayProps;
@@ -60,6 +65,7 @@ export function useReactAriaPopover(
boundaryElement,
isDismissable = true,
shouldCloseOnBlur = true,
+ shouldCloseOnScroll = true,
placement: placementProp = "top",
containerPadding,
shouldCloseOnInteractOutside,
@@ -102,7 +108,7 @@ export function useReactAriaPopover(
containerPadding,
placement: toReactAriaPlacement(placementProp),
offset: showArrow ? offset + 3 : offset,
- onClose: isNonModal ? state.close : () => {},
+ onClose: isNonModal && shouldCloseOnScroll ? state.close : () => {},
});
useSafeLayoutEffect(() => {
diff --git a/packages/components/popover/src/use-popover.ts b/packages/components/popover/src/use-popover.ts
index 66321c6968..81641db1ed 100644
--- a/packages/components/popover/src/use-popover.ts
+++ b/packages/components/popover/src/use-popover.ts
@@ -118,6 +118,7 @@ export function usePopover(originalProps: UsePopoverProps) {
boundaryElement,
isKeyboardDismissDisabled,
shouldCloseOnInteractOutside,
+ shouldCloseOnScroll,
motionProps,
className,
classNames,
@@ -169,6 +170,7 @@ export function usePopover(originalProps: UsePopoverProps) {
containerPadding,
updatePositionDeps,
isKeyboardDismissDisabled,
+ shouldCloseOnScroll,
shouldCloseOnInteractOutside,
},
state,
diff --git a/packages/components/popover/stories/popover.stories.tsx b/packages/components/popover/stories/popover.stories.tsx
index 38e7dab459..72f7efdf04 100644
--- a/packages/components/popover/stories/popover.stories.tsx
+++ b/packages/components/popover/stories/popover.stories.tsx
@@ -81,6 +81,11 @@ export default {
type: "boolean",
},
},
+ shouldCloseOnScroll: {
+ control: {
+ type: "boolean",
+ },
+ },
disableAnimation: {
control: {
type: "boolean",