Skip to content

Commit

Permalink
fix: allow controlled InputSearch to be cleared by passing empty string
Browse files Browse the repository at this point in the history
  • Loading branch information
wp-aberg committed Dec 11, 2024
1 parent ee0b2e9 commit f874afd
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 27 deletions.
15 changes: 14 additions & 1 deletion packages/kit/src/input-search/InputSearchInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,26 @@ export const InputSearchInput = React.forwardRef<
}
}, [state.selectionManager.focusedKey, setTempText]);

if (value) {
if (value !== undefined && value !== null) {
inputProps.value = value;
}

if (autocomplete && withKeyboard.current) {
inputProps.value = tempText;
}

const [, setRerender] = React.useState(false);
if (!inputProps.value && inputRef.current) {
const el = inputRef.current as HTMLInputElement;
if (el.value) {
// if a controlled input is passed an empty value,
// an extra render is needed to reset the input's internal state
requestAnimationFrame(() => {
setRerender((prev) => !prev);
});
}
}

const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
withKeyboard.current = true;
Expand Down
71 changes: 45 additions & 26 deletions packages/kit/src/input-search/play.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -223,34 +223,44 @@ export const Scroll = {
const ControlledTemplate: StoryFn<typeof InputSearch.Root> = (args) => {
const [term, setTerm] = useState("");
return (
<Box css={{ width: "275px" }}>
<InputSearch.Root
{...args}
aria-label="Example-Search"
openOnFocus
onSelect={(value) => {
setTerm(value);
<>
<button
onClick={() => {
setTerm("");
}}
>
<InputSearch.Input
name="fruit"
id="fruit"
value={term}
onChange={(event) => {
setTerm(event.target.value);
External Clear
</button>
<br />
<Box css={{ width: "275px" }}>
<InputSearch.Root
{...args}
aria-label="Example-Search"
openOnFocus
onSelect={(value) => {
setTerm(value);
}}
/>
<InputSearch.Popover>
<InputSearch.List>
<InputSearch.ListItem value="Apple" />
<InputSearch.ListItem value="Banana" />
<InputSearch.ListItem value="Orange" />
<InputSearch.ListItem value="Kiwi" />
<InputSearch.ListItem value="Pineapple" />
</InputSearch.List>
</InputSearch.Popover>
</InputSearch.Root>
</Box>
>
<InputSearch.Input
name="fruit"
id="fruit"
value={term}
onChange={(event) => {
setTerm(event.target.value);
}}
/>
<InputSearch.Popover>
<InputSearch.List>
<InputSearch.ListItem value="Apple" />
<InputSearch.ListItem value="Banana" />
<InputSearch.ListItem value="Orange" />
<InputSearch.ListItem value="Kiwi" />
<InputSearch.ListItem value="Pineapple" />
</InputSearch.List>
</InputSearch.Popover>
</InputSearch.Root>
</Box>
</>
);
};

Expand Down Expand Up @@ -298,7 +308,7 @@ export const ControlledKeyboardInteractions = {

play: async () => {
const input = await screen.findByLabelText("Search");
await userEvent.type(input, "app", {
await userEvent.type(input, "test", {
delay: 100,
});
await userEvent.keyboard("[ArrowDown]");
Expand All @@ -310,5 +320,14 @@ export const ControlledKeyboardInteractions = {
const clearButton = await screen.findByText("Clear");
await userEvent.click(clearButton);
await expect(input).toHaveDisplayValue("");
await userEvent.type(input, "test", {
delay: 100,
});
await userEvent.keyboard("[ArrowDown]");
await expect(input).toHaveDisplayValue("Apple");
const externalClearButton = await screen.findByText("External Clear");
await userEvent.click(externalClearButton);
await expect(input).toHaveDisplayValue("");
//
},
};

0 comments on commit f874afd

Please sign in to comment.