fix(dropdown): respect closeOnSelect prop on DropdownItem (#2598)

* fix(dropdown): fix dropdown menu unexpected close when closeOnSelect is false (#2290)

* feat(changeset): Updated DropdownMenu to respect closeOnSelect prop on DropdownItem

* fix(dropdown): add Template

* fix(dropdown): add tests

* fix(dropdown): fixing logic gaps

* fix(changeset): incorrect package name

---------

Co-authored-by: աɨռɢӄաօռɢ <wingkwong.code@gmail.com>
This commit is contained in:
Gtio 2024-08-16 16:47:24 +08:00 committed by GitHub
parent 197386404f
commit 4f8ae50cf4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 95 additions and 1 deletions

View File

@ -0,0 +1,5 @@
---
"@nextui-org/dropdown": patch
---
fix(dropdown): respect closeOnSelect prop on DropdownItem (#2290)

View File

@ -795,4 +795,40 @@ describe("Keyboard interactions", () => {
logSpy.mockRestore();
});
it("should respect closeOnSelect setting of DropdownItem", async () => {
const onOpenChange = jest.fn();
const wrapper = render(
<Dropdown onOpenChange={onOpenChange}>
<DropdownTrigger>
<Button data-testid="trigger-test">Trigger</Button>
</DropdownTrigger>
<DropdownMenu aria-label="Actions">
<DropdownItem key="new" closeOnSelect={false}>
New file
</DropdownItem>
<DropdownItem key="copy">Copy link</DropdownItem>
</DropdownMenu>
</Dropdown>,
);
let triggerButton = wrapper.getByTestId("trigger-test");
act(() => {
triggerButton.click();
});
expect(onOpenChange).toBeCalledTimes(1);
let menuItems = wrapper.getAllByRole("menuitem");
await act(async () => {
await userEvent.click(menuItems[0]);
expect(onOpenChange).toBeCalledTimes(1);
});
await act(async () => {
await userEvent.click(menuItems[1]);
expect(onOpenChange).toBeCalledTimes(2);
});
});
});

View File

@ -152,7 +152,17 @@ export function useDropdown(props: UseDropdownProps) {
menuProps,
closeOnSelect,
...mergeProps(props, {
onAction: () => onMenuAction(props?.closeOnSelect),
onAction: (key: any) => {
// @ts-ignore
const item = props?.children?.find((item) => item.key === key);
if (item?.props?.closeOnSelect === false) {
onMenuAction(false);
return;
}
onMenuAction(props?.closeOnSelect);
},
onClose: state.close,
}),
} as MenuProps;

View File

@ -153,6 +153,41 @@ const Template = ({color, variant, ...args}: DropdownProps & DropdownMenuProps)
</Dropdown>
);
const ItemCloseOnSelectTemplate = ({
color,
variant,
...args
}: DropdownProps & DropdownMenuProps) => (
<>
<Dropdown {...args}>
<DropdownTrigger>
<Button>Trigger</Button>
</DropdownTrigger>
<DropdownMenu aria-label="Actions" color={color} variant={variant}>
<DropdownItem key="new">New file</DropdownItem>
<DropdownItem key="copy">Copy link</DropdownItem>
<DropdownItem key="edit">Edit file</DropdownItem>
<DropdownItem key="delete" className="text-danger" closeOnSelect={false} color="danger">
Delete file
</DropdownItem>
</DropdownMenu>
</Dropdown>
<Dropdown {...args}>
<DropdownTrigger>
<Button>Trigger</Button>
</DropdownTrigger>
<DropdownMenu aria-label="Actions" closeOnSelect={false} color={color} variant={variant}>
<DropdownItem key="new">New file</DropdownItem>
<DropdownItem key="copy">Copy link</DropdownItem>
<DropdownItem key="edit">Edit file</DropdownItem>
<DropdownItem key="delete" className="text-danger" color="danger">
Delete file
</DropdownItem>
</DropdownMenu>
</Dropdown>
</>
);
const DynamicTemplate = ({color, variant, ...args}: DropdownProps & DropdownMenuProps) => (
<Dropdown {...args}>
<DropdownTrigger>
@ -739,3 +774,11 @@ export const DisableAnimation = {
disableAnimation: true,
},
};
export const ItemCloseOnSelect = {
render: ItemCloseOnSelectTemplate,
args: {
...defaultProps,
},
};