diff --git a/src/components/widgets/search/search.jsx b/src/components/widgets/search/search.jsx
index 486b89ccf..c41e299ca 100644
--- a/src/components/widgets/search/search.jsx
+++ b/src/components/widgets/search/search.jsx
@@ -139,6 +139,8 @@ export default function Search({ options }) {
}, [selectedProvider, options, query, searchSuggestions]);
function doSearch(value) {
+ if (!value) return;
+
const q = encodeURIComponent(value);
const { url } = selectedProvider;
if (url) {
diff --git a/src/components/widgets/search/search.test.jsx b/src/components/widgets/search/search.test.jsx
index 6c0fb0328..dee084dce 100644
--- a/src/components/widgets/search/search.test.jsx
+++ b/src/components/widgets/search/search.test.jsx
@@ -24,7 +24,19 @@ vi.mock("@headlessui/react", async () => {
{children}
),
- ComboboxInput: (props) => ,
+ ComboboxInput: (props) => {
+ const ctx = useContext(ComboboxContext);
+ // real headlessui fires onChange(null) when the input is cleared
+ return (
+ {
+ props.onChange?.(event);
+ if (event.target.value === "") ctx?.onChange?.(null);
+ }}
+ />
+ );
+ },
ComboboxOption: ({ as: As = "div", value, children, ...props }) => {
const ctx = useContext(ComboboxContext);
const content = typeof children === "function" ? children({ active: false }) : children;
@@ -83,6 +95,21 @@ describe("components/widgets/search", () => {
openSpy.mockRestore();
});
+ it("does not search when the input is cleared", () => {
+ const openSpy = vi.spyOn(window, "open").mockImplementation(() => null);
+
+ renderWithProviders(, {
+ settings: {},
+ });
+
+ const input = screen.getByPlaceholderText("search.placeholder");
+ fireEvent.change(input, { target: { value: "a" } });
+ fireEvent.change(input, { target: { value: "" } });
+
+ expect(openSpy).not.toHaveBeenCalled();
+ openSpy.mockRestore();
+ });
+
it("accepts provider configured as a string", () => {
const openSpy = vi.spyOn(window, "open").mockImplementation(() => null);