Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(popover): added control for closing popover on scroll #3595

Merged
Merged
5 changes: 5 additions & 0 deletions .changeset/slow-paws-punch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nextui-org/popover": minor
---

added `shouldCloseOnScroll` to control the popover closing on scroll (#3594)
3 changes: 2 additions & 1 deletion apps/docs/content/docs/components/popover.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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. | |
Expand Down
33 changes: 33 additions & 0 deletions packages/components/popover/__tests__/popover.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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(
<Popover shouldCloseOnScroll={false}>
<PopoverTrigger>
<Button data-testid="popover">Open popover</Button>
</PopoverTrigger>
<PopoverContent>
<Select data-testid="select" label="Select country">
<SelectItem key="argentina">Argentina</SelectItem>
<SelectItem key="venezuela">Venezuela</SelectItem>
<SelectItem key="brazil">Brazil</SelectItem>
</Select>
</PopoverContent>
</Popover>,
);

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");
});
8 changes: 7 additions & 1 deletion packages/components/popover/src/use-aria-popover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<AriaPopoverProps, "placement"> & AriaOverlayProps;
Expand All @@ -60,6 +65,7 @@ export function useReactAriaPopover(
boundaryElement,
isDismissable = true,
shouldCloseOnBlur = true,
shouldCloseOnScroll = true,
placement: placementProp = "top",
containerPadding,
shouldCloseOnInteractOutside,
Expand Down Expand Up @@ -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(() => {
Expand Down
2 changes: 2 additions & 0 deletions packages/components/popover/src/use-popover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ export function usePopover(originalProps: UsePopoverProps) {
boundaryElement,
isKeyboardDismissDisabled,
shouldCloseOnInteractOutside,
shouldCloseOnScroll,
motionProps,
className,
classNames,
Expand Down Expand Up @@ -169,6 +170,7 @@ export function usePopover(originalProps: UsePopoverProps) {
containerPadding,
updatePositionDeps,
isKeyboardDismissDisabled,
shouldCloseOnScroll,
shouldCloseOnInteractOutside,
},
state,
Expand Down
5 changes: 5 additions & 0 deletions packages/components/popover/stories/popover.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ export default {
type: "boolean",
},
},
shouldCloseOnScroll: {
control: {
type: "boolean",
},
},
disableAnimation: {
control: {
type: "boolean",
Expand Down