Skip to content

Commit

Permalink
fix(autocomplete): popover should remain open after clicking clear bu…
Browse files Browse the repository at this point in the history
…tton (#3788)

* fix: add state.open() so that dropdown is not closed

* chore: add changeset

* chore(autocomplete): add testcases for keeping lisbox open when clearButton is clicked

* chore: update changeset

* chore(autocomplete): change the docs for test cases

* chore(changeset): update changeset message and add issue number

---------

Co-authored-by: WK Wong <wingkwong.code@gmail.com>
  • Loading branch information
abhinav700 and wingkwong authored Sep 28, 2024
1 parent 06c4b2f commit 2e82f16
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/dirty-moles-refuse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nextui-org/autocomplete": patch
---

Clicking the clear button clears the selected value without closing the dropdown. (#3788)
94 changes: 92 additions & 2 deletions packages/components/autocomplete/__tests__/autocomplete.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ describe("Autocomplete", () => {

expect(clearButton).not.toBeNull();

// select the target item
// click the clear button
await act(async () => {
await userEvent.click(clearButton);
});
Expand All @@ -235,6 +235,55 @@ describe("Autocomplete", () => {
expect(autocomplete).toHaveFocus();
});

it("should keep the ListBox open after clicking clear button", async () => {
const wrapper = render(
<Autocomplete aria-label="Favorite Animal" data-testid="autocomplete" label="Favorite Animal">
<AutocompleteItem key="penguin" value="penguin">
Penguin
</AutocompleteItem>
<AutocompleteItem key="zebra" value="zebra">
Zebra
</AutocompleteItem>
<AutocompleteItem key="shark" value="shark">
Shark
</AutocompleteItem>
</Autocomplete>,
);

const autocomplete = wrapper.getByTestId("autocomplete");

// open the select listbox
await act(async () => {
await userEvent.click(autocomplete);
});

// assert that the autocomplete listbox is open
expect(autocomplete).toHaveAttribute("aria-expanded", "true");

let options = wrapper.getAllByRole("option");

// select the target item
await act(async () => {
await userEvent.click(options[0]);
});

const {container} = wrapper;

const clearButton = container.querySelector(
"[data-slot='inner-wrapper'] button:nth-of-type(1)",
)!;

expect(clearButton).not.toBeNull();

// click the clear button
await act(async () => {
await userEvent.click(clearButton);
});

// assert that the autocomplete listbox is open
expect(autocomplete).toHaveAttribute("aria-expanded", "true");
});

it("should clear value after clicking clear button (controlled)", async () => {
const wrapper = render(
<ControlledAutocomplete data-testid="autocomplete" items={itemsData}>
Expand Down Expand Up @@ -267,7 +316,7 @@ describe("Autocomplete", () => {

expect(clearButton).not.toBeNull();

// select the target item
/// click the clear button
await act(async () => {
await userEvent.click(clearButton);
});
Expand All @@ -279,6 +328,47 @@ describe("Autocomplete", () => {
expect(autocomplete).toHaveFocus();
});

it("should keep the ListBox open after clicking clear button (controlled)", async () => {
const wrapper = render(
<ControlledAutocomplete data-testid="autocomplete" items={itemsData}>
{(item) => <AutocompleteItem key={item.value}>{item.value}</AutocompleteItem>}
</ControlledAutocomplete>,
);

const autocomplete = wrapper.getByTestId("autocomplete");

// open the select listbox
await act(async () => {
await userEvent.click(autocomplete);
});

// assert that the autocomplete listbox is open
expect(autocomplete).toHaveAttribute("aria-expanded", "true");

let options = wrapper.getAllByRole("option");

// select the target item
await act(async () => {
await userEvent.click(options[0]);
});

const {container} = wrapper;

const clearButton = container.querySelector(
"[data-slot='inner-wrapper'] button:nth-of-type(1)",
)!;

expect(clearButton).not.toBeNull();

// click the clear button
await act(async () => {
await userEvent.click(clearButton);
});

// assert that the autocomplete listbox is open
expect(autocomplete).toHaveAttribute("aria-expanded", "true");
});

it("should open and close listbox by clicking selector button", async () => {
const wrapper = render(
<Autocomplete aria-label="Favorite Animal" data-testid="autocomplete" label="Favorite Animal">
Expand Down
3 changes: 1 addition & 2 deletions packages/components/autocomplete/src/use-autocomplete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -385,16 +385,15 @@ export function useAutocomplete<T extends object>(originalProps: UseAutocomplete
},
onPress: (e: PressEvent) => {
slotsProps.clearButtonProps?.onPress?.(e);

if (state.selectedItem) {
state.setInputValue("");
state.setSelectedKey(null);
} else {
if (allowsCustomValue) {
state.setInputValue("");
state.close();
}
}
state.open();
},
"data-visible": !!state.selectedItem || state.inputValue?.length > 0,
className: slots.clearButton({
Expand Down

0 comments on commit 2e82f16

Please sign in to comment.