Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

style(inputsearch): change default html clear icon #607

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ exports[`<Autocomplete /> Default story renders snapshot 1`] = `
Search by label
</label>
<div
class="MuiFormControl-root MuiTextField-root css-zhsnsf-MuiFormControl-root-MuiTextField-root"
class="MuiFormControl-root MuiTextField-root css-csl8fy-MuiFormControl-root-MuiTextField-root"
>
<div
class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-colorPrimary MuiInputBase-formControl MuiInputBase-sizeSmall MuiInputBase-adornedEnd css-o9k5xi-MuiInputBase-root-MuiOutlinedInput-root"
Expand All @@ -39,9 +39,11 @@ exports[`<Autocomplete /> Default story renders snapshot 1`] = `
value=""
/>
<div
class="MuiInputAdornment-root MuiInputAdornment-positionEnd MuiInputAdornment-outlined MuiInputAdornment-sizeSmall css-1laqsz7-MuiInputAdornment-root"
class="MuiInputAdornment-root MuiInputAdornment-positionEnd MuiInputAdornment-outlined MuiInputAdornment-sizeSmall css-g8kzra-MuiInputAdornment-root"
>

<button
aria-label="search-button"
class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeMedium css-1fqpm4w-MuiButtonBase-root-MuiIconButton-root"
tabindex="0"
type="button"
Expand Down
30 changes: 27 additions & 3 deletions packages/components/src/core/Autocomplete/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import {
AutocompleteInputChangeReason,
AutocompleteRenderInputParams,
AutocompleteRenderOptionState,
InputAdornment,
AutocompleteProps as MuiAutocompleteProps,
} from "@mui/material";
import React, { ReactNode, SyntheticEvent, useState } from "react";
import { noop } from "src/common/utils";
import ButtonIcon from "../ButtonIcon";
import { IconProps } from "../Icon";
import { InputSearchProps } from "../InputSearch";
import { StyledInputAdornment } from "../InputSearch/style";
import MenuItem, { IconNameToSmallSizes } from "../MenuItem";
import {
InputBaseWrapper,
Expand Down Expand Up @@ -147,13 +147,27 @@ const Autocomplete = <
*/
...params.InputProps.ref,
endAdornment: (
<InputAdornment position="end">
<StyledInputAdornment position="end">
Copy link
Contributor Author

@masoudmanson masoudmanson Sep 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the Autocomplete component overrides the InputSearch's endAdornment, we must also include the clear IconButton here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feels like it's worth adding this comment in the code!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, sure :D

{inputValue && (
<ButtonIcon
aria-label="clear-button"
className="input-search-clear-icon"
onClick={clearInput}
sdsType="primary"
sdsSize="small"
sdsIconProps={{
sdsType: "iconButton",
}}
sdsIcon="xMark"
/>
)}
<ButtonIcon
aria-label="search-button"
sdsType="secondary"
sdsSize="small"
sdsIcon="search"
/>
</InputAdornment>
</StyledInputAdornment>
),
inputProps: params.inputProps,
}}
Expand Down Expand Up @@ -193,6 +207,16 @@ const Autocomplete = <
/>
);

function clearInput() {
setInputValue("");
if (onInputChange)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because we are manually firing this event, we must build a onChange event to transmit the updated value to onChange listeners.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's add this context comment in the code too please 🙏

onInputChange(
{ target: { value: "" } } as React.ChangeEvent<HTMLInputElement>,
"",
"clear"
);
}

function defaultGetOptionLabel(
option: T | AutocompleteFreeSoloValueMapping<FreeSolo>
): string {
Expand Down
45 changes: 37 additions & 8 deletions packages/components/src/core/InputSearch/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import {
InputAdornment,
TextFieldProps as RawTextFieldSearchProps,
} from "@mui/material";
import { TextFieldProps as RawTextFieldSearchProps } from "@mui/material";
import React, { forwardRef, useState } from "react";
import ButtonIcon from "../ButtonIcon";
import { InputSearchExtraProps, StyledLabel, StyledSearchBase } from "./style";
import {
InputSearchExtraProps,
StyledInputAdornment,
StyledLabel,
StyledSearchBase,
} from "./style";

export interface AccessibleInputSearchProps {
label: string;
Expand Down Expand Up @@ -50,6 +52,19 @@ const InputSearch = forwardRef<HTMLDivElement, InputSearchProps>(
if (onChange) onChange(event);
};

const clearInput = () => {
setValue("");
setHasValue(false);

if (handleSubmit) handleSubmit("");

if (onChange) {
onChange({
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the Autocomplete component, Because we are manually firing this event, we must build a onChange event to transmit the updated value to onChange listeners.

target: { value: "" },
} as React.ChangeEvent<HTMLInputElement>);
}
};

const localHandleSubmit = () => {
if (handleSubmit) handleSubmit(value);
};
Expand Down Expand Up @@ -77,7 +92,20 @@ const InputSearch = forwardRef<HTMLDivElement, InputSearchProps>(
// passed to mui Input
InputProps={{
endAdornment: (
<InputAdornment position="end">
<StyledInputAdornment position="end">
{value && (
<ButtonIcon
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I replaced the default HTML clear icon for search inputs with an SDS xMark icon as an input adornment at the end of the input.

aria-label="clear-button"
className="input-search-clear-icon"
onClick={clearInput}
sdsType="primary"
sdsSize="small"
sdsIconProps={{
sdsType: "iconButton",
}}
sdsIcon="xMark"
/>
)}
<ButtonIcon
aria-label="search-button"
onClick={localHandleSubmit}
Expand All @@ -88,7 +116,7 @@ const InputSearch = forwardRef<HTMLDivElement, InputSearchProps>(
}}
sdsIcon="search"
/>
</InputAdornment>
</StyledInputAdornment>
),
}}
type="search"
Expand All @@ -100,8 +128,9 @@ const InputSearch = forwardRef<HTMLDivElement, InputSearchProps>(
sdsStyle={sdsStyle}
sdsStage={hasValue ? "userInput" : "default"}
onChange={handleChange}
onKeyPress={handleKeyPress}
onKeyDown={handleKeyPress}
intent={intent}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The onKeyPress event has been deprecated and replaced by the newer onKeyDown event.

autoComplete="off"
{...rest}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This prevents the browser's default auto completion menu from being displayed for the InputSearch.

Screenshot 2023-09-21 at 5 08 16 PM

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add this comment in the code too for context!

/>
</>
Expand Down
23 changes: 22 additions & 1 deletion packages/components/src/core/InputSearch/style.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { css, SerializedStyles } from "@emotion/react";
import {
InputAdornment,
inputAdornmentClasses,
inputBaseClasses,
outlinedInputClasses,
Expand Down Expand Up @@ -116,14 +117,30 @@ export const StyledSearchBase = styled(TextField, {
min-width: 120px;
display: block;

[type="search"]::-webkit-search-cancel-button {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part hides the default HTML clear icon.

-webkit-appearance: none;
appearance: none;
}

& .input-search-clear-icon {
display: none;
position: absolute;
right: 20px;
}

.${outlinedInputClasses.root} {
.${outlinedInputClasses.notchedOutline} {
border: ${borders?.gray[400]};
}

&:hover .input-search-clear-icon,
&:focus-within .input-search-clear-icon {
display: inline-flex;
}
}

.${inputBaseClasses.inputSizeSmall} {
padding: ${spacings?.xs}px 0 ${spacings?.xs}px ${spacings?.l}px;
padding: ${spacings?.xs}px ${spacings?.l}px;
height: 34px;
box-sizing: border-box;
background-color: #fff;
Expand Down Expand Up @@ -151,3 +168,7 @@ export const StyledSearchBase = styled(TextField, {
`;
}}
`;

export const StyledInputAdornment = styled(InputAdornment)`
position: relative;
`;
Loading