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-1rjsjzb-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 All @@ -51,7 +53,7 @@ exports[`<Autocomplete /> Default story renders snapshot 1`] = `
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-1q6hio5-MuiSvgIcon-root"
class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-tr2xv3-MuiSvgIcon-root"
data-file-name="IconSearchSmall"
data-testid="IconSearchSmall"
fillcontrast="white"
Expand Down
41 changes: 38 additions & 3 deletions packages/components/src/core/Autocomplete/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
AutocompleteInputChangeReason,
AutocompleteRenderInputParams,
AutocompleteRenderOptionState,
InputAdornment,
AutocompleteProps as MuiAutocompleteProps,
Popper,
PopperProps,
Expand All @@ -13,6 +12,7 @@ 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 @@ -171,13 +171,34 @@ 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

{/**
* (masoudmansdon): Because the Autocomplete component overrides the
* InputSearch's endAdornment, we must also include the clear IconButton here.
*/}
{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"
sdsIconProps={{
sdsType: "interactive",
}}
sdsIcon="search"
/>
</InputAdornment>
</StyledInputAdornment>
),
inputProps: params.inputProps,
}}
Expand Down Expand Up @@ -217,6 +238,20 @@ const Autocomplete = <
/>
);

function clearInput() {
setInputValue("");
/**
* (masoudmanson): Because we are manually firing this event,
* we must build a onChange event to transmit the updated value to onChange listeners.
*/
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
2 changes: 1 addition & 1 deletion packages/components/src/core/Autocomplete/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ export const StyledPaper = styled(Paper)`
const shadows = getShadows(props);
return `
padding: ${spacings?.s}px 0 0 ${spacings?.s}px ;
padding: ${spacings?.s}px 0 0 ${spacings?.s}px;
background-color: white;
border: ${borders?.gray[100]};
border-radius: ${corners?.m}px;
Expand Down
14 changes: 13 additions & 1 deletion packages/components/src/core/Dropdown/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ const Dropdown = (props: Args): JSX.Element => {
onChange={noop}
options={GITHUB_LABELS}
DropdownMenuProps={{
PopperBaseProps: {
sx: { width: "300px" },
},
groupBy: (option: DefaultDropdownMenuOption) =>
option.section as string,
}}
Expand Down Expand Up @@ -150,7 +153,7 @@ export const InsideModal = {
skip: true,
},
},
render: function InsideModalComponent(): JSX.Element {
render: function InsideModalComponent(props: Args): JSX.Element {
const [value, setValue] = useState<
DefaultDropdownMenuOption | DefaultDropdownMenuOption[] | null
>([GITHUB_LABELS[0], GITHUB_LABELS[1]]);
Expand All @@ -168,6 +171,7 @@ export const InsideModal = {
value={value}
multiple
InputDropdownProps={{ sdsStyle: "square" }}
{...props}
/>
</Dialog>
);
Expand Down Expand Up @@ -206,6 +210,9 @@ const ControlledDropdownDemo = (props: Args): JSX.Element => {
onChange={handleChange}
data-testid="dropdown"
DropdownMenuProps={{
PopperBaseProps: {
sx: { width: "300px" },
},
groupBy: (option: DefaultDropdownMenuOption) =>
option.section as string,
title: "Github Labels",
Expand Down Expand Up @@ -244,6 +251,11 @@ const TestDemo = (props: Args): JSX.Element => {
label="Click Target"
onChange={noop}
options={GITHUB_LABELS}
DropdownMenuProps={{
PopperBaseProps: {
sx: { width: "300px" },
},
}}
{...props}
data-testid="dropdown"
/>
Expand Down
51 changes: 43 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,23 @@ const InputSearch = forwardRef<HTMLDivElement, InputSearchProps>(
if (onChange) onChange(event);
};

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

if (handleSubmit) handleSubmit("");

/**
* (masoudmanson): Because we are manually firing this event,
* we must build a onChange event to transmit the updated value to onChange listeners.
*/
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 +96,18 @@ const InputSearch = forwardRef<HTMLDivElement, InputSearchProps>(
// passed to mui Input
InputProps={{
endAdornment: (
<InputAdornment position="end">
<StyledInputAdornment position="end">
<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"
onClick={localHandleSubmit}
Expand All @@ -88,7 +118,7 @@ const InputSearch = forwardRef<HTMLDivElement, InputSearchProps>(
}}
sdsIcon="search"
/>
</InputAdornment>
</StyledInputAdornment>
),
}}
type="search"
Expand All @@ -100,8 +130,13 @@ 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.

/**
* (masoudmanson): This prevents the browser's default auto completion
* menu from being displayed for the InputSearch.
*/
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
33 changes: 29 additions & 4 deletions packages/components/src/core/InputSearch/style.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { css, SerializedStyles } from "@emotion/react";
import {
buttonBaseClasses,
InputAdornment,
inputAdornmentClasses,
inputBaseClasses,
outlinedInputClasses,
Expand All @@ -21,6 +23,7 @@ export interface InputSearchExtraProps extends CommonThemeProps {
intent?: "default" | "error" | "warning";
sdsStyle?: "rounded" | "square";
sdsStage?: "default" | "userInput";
value?: string;
}

const sdsPropNames = ["sdsStyle", "sdsStage", "intent", "handleSubmit"];
Expand Down Expand Up @@ -104,7 +107,7 @@ export const StyledSearchBase = styled(TextField, {
},
})`
${(props: InputSearchExtraProps) => {
const { intent, disabled, sdsStyle } = props;
const { intent, disabled, sdsStyle, value } = props;
const spacings = getSpaces(props);
const borders = getBorders(props);
const colors = getColors(props);
Expand All @@ -116,14 +119,29 @@ 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 {
opacity: 0;
margin-right: ${spacings?.s}px;
}

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

&:hover .input-search-clear-icon,
&:focus-within .input-search-clear-icon {
opacity: ${value ? 1 : 0};
}
}

.${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 All @@ -139,8 +157,11 @@ export const StyledSearchBase = styled(TextField, {
border: ${borders?.primary[400]};
}

.${inputAdornmentClasses.root} svg {
color: ${colors?.primary[400]};
.${inputAdornmentClasses.root} .${buttonBaseClasses.root}:last-of-type {
cursor: default;
svg {
color: ${colors?.primary[400]};
}
}
}

Expand All @@ -151,3 +172,7 @@ export const StyledSearchBase = styled(TextField, {
`;
}}
`;

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