Skip to content

Commit

Permalink
Merge pull request #6847 from Sage/FE-6664-search-close-click
Browse files Browse the repository at this point in the history
feat(search): add `triggerOnClear` prop to allow clicking `cross` icon to trigger `onClick` FE-6664
  • Loading branch information
edleeks87 committed Aug 1, 2024
2 parents cecc0de + 3059634 commit cd4cd1a
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 3 deletions.
38 changes: 37 additions & 1 deletion src/components/search/search-test.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React, { useState } from "react";
import { action } from "@storybook/addon-actions";
import Pill from "../pill/pill.component";
import Search, { SearchProps } from ".";
import { SearchEvent } from "./search.component";

export default {
title: "Search/Test",
includeStories: ["Default"],
includeStories: ["Default", "FilterOnClear"],
parameters: {
info: { disable: true },
chromatic: {
Expand Down Expand Up @@ -80,3 +81,38 @@ export const SearchComponent = (props: SearchProps) => {
/>
);
};

export const FilterOnClear = () => {
const [value, setValue] = useState("");
const textArray = ["test value 1", "test value 2", "test value 3"];
const [filteredText, setFilteredText] = useState(textArray);

const updateFilteredElements = (searchValue: string) => {
if (searchValue === "") {
setFilteredText(textArray);
} else {
setFilteredText(textArray.filter((text) => text.includes(searchValue)));
}
};
return (
<>
<Search
id="test"
name="test"
placeholder="Search..."
triggerOnClear
onClick={(e) => updateFilteredElements(e.target.value)}
onChange={(e) => setValue(e.target.value)}
value={value}
searchButton
/>

<div>
{filteredText.map((text) => (
<Pill key={text}>{text}</Pill>
))}
</div>
</>
);
};
FilterOnClear.storyName = "Filter on clear";
18 changes: 16 additions & 2 deletions src/components/search/search.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ export interface SearchProps extends ValidationProps, MarginProps {
* `onClick` events are triggered when the `searchButton` is clicked
*/
onClick?: (ev: SearchEvent) => void;

/**
* Sets whether the onClick action should be triggered when the Search cross icon is clicked.
*/
triggerOnClear?: boolean;
/** Prop for `onFocus` events */
onFocus?: (ev: React.FocusEvent<HTMLInputElement>) => void;
/** Prop for `onKeyDown` events */
Expand Down Expand Up @@ -101,6 +106,7 @@ export const Search = React.forwardRef<SearchHandle, SearchProps>(
warning,
info,
tooltipPosition,
triggerOnClear,
...rest
},
ref
Expand Down Expand Up @@ -176,8 +182,16 @@ export const Search = React.forwardRef<SearchHandle, SearchProps>(
const handleIconClick = () => {
setSearchValue("");

if (onChange) {
onChange({
onChange?.({
target: {
...(name && { name }),
...(id && { id }),
value: "",
},
});

if (triggerOnClear) {
onClick?.({
target: {
...(name && { name }),
...(id && { id }),
Expand Down
7 changes: 7 additions & 0 deletions src/components/search/search.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,13 @@ It is possible to use the `tooltipPosition` to override the default placement of

<Canvas of={SearchStories.ValidationsBoolean} />

#### When cross icon clicked

It is possible to trigger actions such as filtering the search results when the cross icon is clicked.
When the `triggerOnClear` prop is set to `true`, the `onClick` callback will be called when the cross icon is clicked.

<Canvas of={SearchStories.WhenCrossIconClicked} />

## Props

### Search
Expand Down
38 changes: 38 additions & 0 deletions src/components/search/search.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -742,3 +742,41 @@ describe("Search", () => {
});
});
});

test("should call `onClick` when it and `triggerOnClear` props are passed and the user clicks the cross icon", async () => {
const onClick = jest.fn();
const user = userEvent.setup();
render(
<Search
value="foo"
onClick={onClick}
triggerOnClear
onChange={() => {}}
searchButton
name="foo"
id="bar"
/>
);
const inputIcon = screen.getByTestId("input-icon-toggle");
await user.click(inputIcon);

expect(onClick).toHaveBeenCalledWith({
target: {
name: "foo",
id: "bar",
value: "",
},
});
});

test("should not call `onClick` when prop is passed and the user clicks the cross icon but `triggerOnClear` is not set", async () => {
const onClick = jest.fn();
const user = userEvent.setup();
render(
<Search value="foo" onClick={onClick} onChange={() => {}} searchButton />
);
const inputIcon = screen.getByTestId("input-icon-toggle");
await user.click(inputIcon);

expect(onClick).not.toHaveBeenCalled();
});
23 changes: 23 additions & 0 deletions src/components/search/search.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -298,3 +298,26 @@ export const ValidationsBoolean: Story = () => {
);
};
ValidationsBoolean.storyName = "Validations - Boolean";

export const WhenCrossIconClicked: Story = () => {
const [value, setValue] = useState("");
return (
<>
<Search
id="test"
name="test"
placeholder="Search..."
triggerOnClear
// eslint-disable-next-line no-console
onClick={(e) => console.log("clicked", e)}
onChange={(e) => setValue(e.target.value)}
value={value}
searchButton
/>
</>
);
};
WhenCrossIconClicked.storyName = "When cross icon clicked";
WhenCrossIconClicked.parameters = {
chromatic: { disableSnapshot: true },
};

0 comments on commit cd4cd1a

Please sign in to comment.