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

Add Odyssey clear button to SearchField #1878

Merged
merged 9 commits into from
Jul 21, 2023
56 changes: 51 additions & 5 deletions packages/odyssey-react-mui/src/SearchField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* See the License for the specific language governing permissions and limitations under the License.
*/

import { useState, useEffect } from "react";
import { InputAdornment, InputBase } from "@mui/material";
import {
ChangeEventHandler,
Expand All @@ -20,8 +21,9 @@ import {
useCallback,
} from "react";

import { SearchIcon } from "./iconDictionary";
import { CloseCircleFilledIcon, SearchIcon } from "./iconDictionary";
import { Field } from "./Field";
import { Button } from "./Button";

export type SearchFieldProps = {
/**
Expand Down Expand Up @@ -50,6 +52,10 @@ export type SearchFieldProps = {
* Callback fired when the `input` element loses focus.
*/
onBlur?: FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>;
/**
* Callback fired when the clear button is pressed.
*/
onClear?: () => void;
/**
* Callback fired when the value is changed.
*/
Expand All @@ -76,21 +82,58 @@ const SearchField = forwardRef<HTMLInputElement, SearchFieldProps>(
id: idOverride,
isDisabled = false,
label,
onChange,
onChange: onChangeProp,
onFocus,
onBlur,
onClear: onClearProp,
placeholder,
value,
value: controlledValue,
},
ref
) => {
const [uncontrolledValue, setUncontrolledValue] = useState("");

const onChange = useCallback(
(e) => {
setUncontrolledValue(e.target.value);
jordankoschei-okta marked this conversation as resolved.
Show resolved Hide resolved
if (onChangeProp) onChangeProp(e);
},
[onChangeProp]
);
jordankoschei-okta marked this conversation as resolved.
Show resolved Hide resolved

const onClear = useCallback(() => {
setUncontrolledValue("");
if (onClearProp) onClearProp();
jordankoschei-okta marked this conversation as resolved.
Show resolved Hide resolved
}, [onClearProp]);

useEffect(() => {
if (controlledValue !== undefined) {
setUncontrolledValue(controlledValue);
}
}, [controlledValue]);

const renderFieldComponent = useCallback(
({ ariaDescribedBy, id }) => (
<InputBase
aria-describedby={ariaDescribedBy}
autoComplete={autoCompleteType}
/* eslint-disable-next-line jsx-a11y/no-autofocus */
autoFocus={hasInitialFocus}
endAdornment={
uncontrolledValue.length > 0 && (
jordankoschei-okta marked this conversation as resolved.
Show resolved Hide resolved
jordankoschei-okta marked this conversation as resolved.
Show resolved Hide resolved
<InputAdornment position="end">
<Button
ariaLabel="Clear"
isDisabled={isDisabled}
onClick={onClear}
size="small"
startIcon={<CloseCircleFilledIcon />}
text=""
variant="floating"
/>
</InputAdornment>
)
}
id={id}
name={id}
onChange={onChange}
Expand All @@ -104,18 +147,21 @@ const SearchField = forwardRef<HTMLInputElement, SearchFieldProps>(
</InputAdornment>
}
type="search"
value={value}
value={
controlledValue !== undefined ? controlledValue : uncontrolledValue
jordankoschei-okta marked this conversation as resolved.
Show resolved Hide resolved
}
/>
),
[
autoCompleteType,
hasInitialFocus,
isDisabled,
jordankoschei-okta marked this conversation as resolved.
Show resolved Hide resolved
onChange,
onFocus,
onBlur,
placeholder,
ref,
value,
uncontrolledValue,
]
jordankoschei-okta marked this conversation as resolved.
Show resolved Hide resolved
);

Expand Down
15 changes: 15 additions & 0 deletions packages/odyssey-react-mui/src/theme/components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1469,6 +1469,21 @@ export const components = (
opacity: "1 !important",
},
},

[`&::-webkit-search-cancel-button`]: {
display: "none",
"-webkit-appearance": "none",
"-moz-appearance": "none",
},

[`&::-moz-search-cancel-button`]: {
display: "none",
"-moz-appearance": "none",
},

[`&::-ms-clear`]: {
display: "none",
},
},
},
},
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -21,40 +21,118 @@ const storybookMeta: Meta<SearchFieldProps> = {
argTypes: {
autoCompleteType: {
control: "text",
description:
"This prop helps users to fill forms faster, especially on mobile devices. The name can be confusing, as it's more like an autofill. You can learn more about it [following the specification](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill)",
table: {
type: {
summary: "string",
},
},
},
hasInitialFocus: {
control: "boolean",
description: "If `true`, the component will receive focus automatically",
table: {
type: {
summary: "boolean",
},
},
},
isDisabled: {
control: "boolean",
description: "If `true`, the component is disabled",
table: {
type: {
summary: "boolean",
},
},
},
id: {
control: "text",
description: "The id of the `input` element",
table: {
type: {
summary: "string",
},
},
},
label: {
control: "text",
description:
"This label won't show up visually, but it's required for accessibility",
table: {
type: {
summary: "string",
},
},
},
onBlur: {
control: "function",
description: "Callback fired when the `input` element loses focus",
table: {
type: {
summary: "function",
},
defaultValue: "",
},
},
onClear: {
control: "function",
description: "Callback fired when the clear button is pressed",
table: {
type: {
summary: "function",
},
defaultValue: "",
},
},
onChange: {
control: "function",
description: "Callback fired when the value is changed",
table: {
type: {
summary: "function",
},
defaultValue: "",
},
},
onFocus: {
control: "function",
description: "Callback fired when the `input` element gets focus",
table: {
type: {
summary: "function",
},
defaultValue: "",
},
},
placeholder: {
control: "text",
description:
"The short hint displayed in the `input` before the user enters a value",
table: {
type: {
summary: "string",
},
},
},
value: {
control: "text",
description:
"The value of the `input` element, required for a controlled component",
table: {
type: {
summary: "string",
},
},
},
},
args: {
label: "Search",
placeholder: "Search planets",
},
decorators: [MuiThemeDecorator],
tags: ["autodocs"],
jordankoschei-okta marked this conversation as resolved.
Show resolved Hide resolved
};

export default storybookMeta;
Expand Down