fix(popover): close popover on scroll (#3414)

* fix(popover): close popover on scroll

* feat(popover): add "should close popover on scroll" test

* feat(changeset): add changeset

* feat(select): add ScrollableContainerTemplate
This commit is contained in:
աӄա 2024-07-06 16:04:56 +08:00 committed by GitHub
parent a164c26e96
commit 444d320dbc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 112 additions and 1 deletions

View File

@ -0,0 +1,5 @@
---
"@nextui-org/popover": patch
---
close popover on scroll (#3265)

View File

@ -314,4 +314,37 @@ describe("Popover", () => {
// assert that the popover is still open
expect(popover).toHaveAttribute("aria-expanded", "true");
});
it("should close popover on scroll", async () => {
const wrapper = render(
<Popover>
<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 closed
expect(popover).toHaveAttribute("aria-expanded", "false");
});
});

View File

@ -102,7 +102,7 @@ export function useReactAriaPopover(
containerPadding,
placement: toReactAriaPlacement(placementProp),
offset: showArrow ? offset + 3 : offset,
onClose: () => {},
onClose: isNonModal ? state.close : () => {},
});
useSafeLayoutEffect(() => {

View File

@ -627,6 +627,71 @@ const WithReactHookFormTemplate = (args: SelectProps) => {
);
};
const ScrollableContainerTemplate = (args: SelectProps) => {
const categories = [
{
target: "Animals",
items: [
{name: "Lion", emoji: "🦁"},
{name: "Tiger", emoji: "🐅"},
{name: "Elephant", emoji: "🐘"},
{name: "Kangaroo", emoji: "🦘"},
{name: "Panda", emoji: "🐼"},
{name: "Giraffe", emoji: "🦒"},
{name: "Zebra", emoji: "🦓"},
{name: "Cheetah", emoji: "🐆"},
],
},
{
target: "Birds",
items: [
{name: "Eagle", emoji: "🦅"},
{name: "Parrot", emoji: "🦜"},
{name: "Penguin", emoji: "🐧"},
{name: "Ostrich", emoji: "🦢"},
{name: "Peacock", emoji: "🦚"},
{name: "Swan", emoji: "🦢"},
{name: "Falcon", emoji: "🦅"},
{name: "Flamingo", emoji: "🦩"},
],
},
];
const DEFAULT_CATEGORY = "Animals";
return (
<>
<form className="h-full overflow-auto">
<div className="flex justify-between h-[1500px]">
<div className="flex items-center gap-2">
<div className="flex w-full flex-wrap gap-4 md:flex-nowrap">
<Select
aria-label="Favourite Animals"
className="w-52"
defaultSelectedKeys={[DEFAULT_CATEGORY]}
label="Category"
name="Category"
{...args}
>
{categories.map((category, idx, arr) => (
<SelectSection
key={category.target}
showDivider={idx !== arr.length - 1}
title={category.target}
>
{category.items.map((item) => (
<SelectItem key={item.name}>{`${item.emoji} ${item.name}`}</SelectItem>
))}
</SelectSection>
))}
</Select>
</div>
</div>
</div>
</form>
</>
);
};
export const Default = {
render: MirrorTemplate,
@ -839,6 +904,14 @@ export const WithReactHookForm = {
},
};
export const WithScrollableContainer = {
render: ScrollableContainerTemplate,
args: {
...defaultProps,
},
};
export const Controlled = {
render: ControlledTemplate,