From 9f7c934dec49104812c025635f9c4dd27ce81043 Mon Sep 17 00:00:00 2001 From: Dawid Date: Fri, 23 Sep 2022 13:39:25 +0200 Subject: [PATCH] Fix dropdown select arrow clicks bugs (#2301) * Fix dropdown arrow click * Fix multi-select dropdown arrow click * Update changelog * Update test snapshots of select inputs * Grey out select dropdowns bottom arrow * Prevent clearing input value in multiselect on item select Co-authored-by: Patryk Andrzejewski --- CHANGELOG.md | 1 + .../MultiAutocompleteSelectField.tsx | 125 +-- .../MultiAutocompleteSelectFieldContent.tsx | 1 + .../MultiAutocompleteSelectField/styles.ts | 71 ++ .../SingleAutocompleteSelectField.tsx | 65 +- .../SingleAutocompleteSelectFieldContent.tsx | 2 +- .../SingleAutocompleteSelectField/styles.ts | 27 + .../__snapshots__/Stories.test.ts.snap | 841 ++---------------- 8 files changed, 221 insertions(+), 912 deletions(-) create mode 100644 src/components/MultiAutocompleteSelectField/styles.ts create mode 100644 src/components/SingleAutocompleteSelectField/styles.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 652b08744..cd2a5a5c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable, unreleased changes to this project will be documented in this file. - Pass query params in `ORDER_DETAILS_MORE_ACTIONS` and `PRODUCT_DETAILS_MORE_ACTIONS` mounting points - #2100 by @witoszekdev - Add product variant reference attribute - #2268 by @droniu +- Fix dropdown select arrow clicks bugs - #2301 by @orzechdev - Fix invalid values in channel picker - #2313 by @orzechdev - Fix missing metadata and payment balance on unconfirmed orders - #2314 by @orzechdev - Fix exit form dialog false positive - #2311 by @orzechdev diff --git a/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx b/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx index c8b2a2043..904ad72c7 100644 --- a/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx +++ b/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx @@ -4,10 +4,9 @@ import { TextField, Typography, } from "@material-ui/core"; -import { fade } from "@material-ui/core/styles/colorManipulator"; import CloseIcon from "@material-ui/icons/Close"; import Debounce, { DebounceProps } from "@saleor/components/Debounce"; -import { ChevronIcon, IconButton, makeStyles } from "@saleor/macaw-ui"; +import { ChevronIcon, IconButton } from "@saleor/macaw-ui"; import { FetchMoreProps } from "@saleor/types"; import classNames from "classnames"; import Downshift, { ControllerStateAndHelpers } from "downshift"; @@ -18,75 +17,7 @@ import MultiAutocompleteSelectFieldContent, { MultiAutocompleteActionType, MultiAutocompleteChoiceType, } from "./MultiAutocompleteSelectFieldContent"; - -const useStyles = makeStyles( - theme => ({ - chip: { - width: "100%", - }, - chipClose: { - height: 32, - padding: 0, - width: 32, - }, - chipContainer: { - display: "flex", - flexDirection: "column", - marginTop: theme.spacing(1), - }, - chipInner: { - "& svg": { - color: theme.palette.primary.contrastText, - }, - alignItems: "center", - background: fade(theme.palette.primary.main, 0.8), - borderRadius: 18, - color: theme.palette.primary.contrastText, - display: "flex", - justifyContent: "space-between", - margin: theme.spacing(1, 0), - paddingLeft: theme.spacing(2), - paddingRight: theme.spacing(1), - }, - chipLabel: { - color: theme.palette.primary.contrastText, - }, - container: { - flexGrow: 1, - position: "relative", - }, - disabledChipInner: { - "& svg": { - color: theme.palette.grey[200], - }, - alignItems: "center", - background: fade(theme.palette.grey[400], 0.8), - borderRadius: 18, - color: theme.palette.primary.contrastText, - display: "flex", - justifyContent: "space-between", - margin: theme.spacing(1, 0), - paddingLeft: theme.spacing(2), - paddingRight: theme.spacing(1), - }, - adornment: { - color: theme.palette.saleor.main[3], - cursor: "pointer", - userSelect: "none", - display: "flex", - alignItems: "center", - "& svg": { - transition: theme.transitions.duration.shorter + "ms", - }, - }, - adornmentRotate: { - "& svg": { - transform: "rotate(180deg)", - }, - }, - }), - { name: "MultiAutocompleteSelectField" }, -); +import { useStyles } from "./styles"; export interface MultiAutocompleteSelectFieldProps extends Partial { @@ -141,14 +72,20 @@ const MultiAutocompleteSelectFieldComponent: React.FC(null); + const anchor = React.useRef(null); + const input = React.useRef(null); + + const [inputValue, setInputValue] = React.useState(""); const handleSelect = ( item: string, downshiftOpts?: ControllerStateAndHelpers, ) => { if (downshiftOpts) { - downshiftOpts.reset({ inputValue: "", isOpen: true }); + downshiftOpts.reset({ + inputValue: downshiftOpts.inputValue, + isOpen: true, + }); } onChange({ target: { name, value: item }, @@ -157,12 +94,17 @@ const MultiAutocompleteSelectFieldComponent: React.FC - + { + setInputValue(value); + fetchChoices(value); + }} + > {debounceFn => ( debounceFn(value)} onSelect={handleSelect} - itemToString={() => ""} + itemToString={() => inputValue} // this is to prevent unwanted state updates when the dropdown is closed with an empty value, // which downshift interprets as the value being updated with an empty string, causing side-effects stateReducer={(state, changes) => { @@ -181,7 +123,6 @@ const MultiAutocompleteSelectFieldComponent: React.FC { const displayCustomValue = inputValue && @@ -192,13 +133,30 @@ const MultiAutocompleteSelectFieldComponent: React.FC { + if (fetchOnFocus) { + fetchChoices(inputValue); + } + input.current.select(); + }; + + const handleToggleMenu = () => { + if (disabled) { + return; + } + toggleMenu(); + }; + return (
{ + handleToggleMenu(); + handleFocus(); + }} className={classNames(classes.adornment, { [classes.adornmentRotate]: isOpen, })} @@ -207,18 +165,15 @@ const MultiAutocompleteSelectFieldComponent: React.FC
), + id: undefined, + onFocus: handleFocus, ref: anchor, - onFocus: () => { - if (fetchOnFocus) { - fetchChoices(inputValue); - } - }, }} inputProps={{ ...getInputProps({ placeholder, testId, - onClick: toggleMenu, + onClick: handleToggleMenu, }), ...getMenuProps(), }} @@ -227,7 +182,9 @@ const MultiAutocompleteSelectFieldComponent: React.FC {isOpen && ( { add.onClick(); diff --git a/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectFieldContent.tsx b/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectFieldContent.tsx index e9f67872b..df3c97a29 100644 --- a/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectFieldContent.tsx +++ b/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectFieldContent.tsx @@ -71,6 +71,7 @@ const useStyles = makeStyles( ? theme.palette.grey[50] : theme.palette.grey[900], bottom: 0, + color: theme.palette.grey[500], display: "flex", height: 30, justifyContent: "center", diff --git a/src/components/MultiAutocompleteSelectField/styles.ts b/src/components/MultiAutocompleteSelectField/styles.ts new file mode 100644 index 000000000..0ebc74a53 --- /dev/null +++ b/src/components/MultiAutocompleteSelectField/styles.ts @@ -0,0 +1,71 @@ +import { fade } from "@material-ui/core/styles/colorManipulator"; +import { makeStyles } from "@saleor/macaw-ui"; + +export const useStyles = makeStyles( + theme => ({ + chip: { + width: "100%", + }, + chipClose: { + height: 32, + padding: 0, + width: 32, + }, + chipContainer: { + display: "flex", + flexDirection: "column", + marginTop: theme.spacing(1), + }, + chipInner: { + "& svg": { + color: theme.palette.primary.contrastText, + }, + alignItems: "center", + background: fade(theme.palette.primary.main, 0.8), + borderRadius: 18, + color: theme.palette.primary.contrastText, + display: "flex", + justifyContent: "space-between", + margin: theme.spacing(1, 0), + paddingLeft: theme.spacing(2), + paddingRight: theme.spacing(1), + }, + chipLabel: { + color: theme.palette.primary.contrastText, + }, + container: { + flexGrow: 1, + position: "relative", + }, + disabledChipInner: { + "& svg": { + color: theme.palette.grey[200], + }, + alignItems: "center", + background: fade(theme.palette.grey[400], 0.8), + borderRadius: 18, + color: theme.palette.primary.contrastText, + display: "flex", + justifyContent: "space-between", + margin: theme.spacing(1, 0), + paddingLeft: theme.spacing(2), + paddingRight: theme.spacing(1), + }, + adornment: { + color: theme.palette.saleor.main[3], + cursor: "pointer", + userSelect: "none", + display: "flex", + alignItems: "center", + "& svg": { + transition: theme.transitions.duration.shorter + "ms", + }, + }, + adornmentRotate: { + "& svg": { + transform: "rotate(180deg)", + }, + }, + }), + { name: "MultiAutocompleteSelectField" }, +); diff --git a/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx b/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx index 6d9cd3509..6e025219a 100644 --- a/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx +++ b/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx @@ -6,7 +6,7 @@ import { } from "@material-ui/core"; import { InputProps } from "@material-ui/core/Input"; import { ExtendedFormHelperTextProps } from "@saleor/channels/components/ChannelForm/types"; -import { ChevronIcon, makeStyles } from "@saleor/macaw-ui"; +import { ChevronIcon } from "@saleor/macaw-ui"; import { FetchMoreProps } from "@saleor/types"; import classNames from "classnames"; import Downshift from "downshift"; @@ -18,32 +18,7 @@ import SingleAutocompleteSelectFieldContent, { SingleAutocompleteActionType, SingleAutocompleteChoiceType, } from "./SingleAutocompleteSelectFieldContent"; - -const useStyles = makeStyles( - theme => ({ - container: { - flexGrow: 1, - position: "relative", - }, - nakedInput: { - padding: theme.spacing(2, 0), - }, - adornment: { - color: theme.palette.saleor.main[3], - cursor: "pointer", - userSelect: "none", - "& svg": { - transition: theme.transitions.duration.shorter + "ms", - }, - }, - adornmentRotate: { - "& svg": { - transform: "rotate(180deg)", - }, - }, - }), - { name: "SingleAutocompleteSelectField" }, -); +import { useStyles } from "./styles"; export interface SingleAutocompleteSelectFieldProps extends Partial { @@ -142,7 +117,6 @@ const SingleAutocompleteSelectFieldComponent: React.FC { const isCustomValueSelected = choices && selectedItem @@ -187,13 +161,30 @@ const SingleAutocompleteSelectFieldComponent: React.FC { + if (fetchOnFocus) { + fetchChoices(inputValue); + } + input.current.select(); + }; + + const handleToggleMenu = () => { + if (disabled) { + return; + } + toggleMenu(); + }; + const TextFieldComponent = nakedInput ? InputBase : TextField; const commonInputProps = { ...InputProps, endAdornment: (
{ + handleToggleMenu(); + handleFocus(); + }} className={classNames(classes.adornment, { [classes.adornmentRotate]: isOpen, })} @@ -203,12 +194,8 @@ const SingleAutocompleteSelectFieldComponent: React.FC { - if (fetchOnFocus) { - fetchChoices(inputValue); - } - input.current.select(); - }, + onFocus: handleFocus, + ref: anchor, }; const nakedInputProps = nakedInput @@ -234,12 +221,7 @@ const SingleAutocompleteSelectFieldComponent: React.FC { - if (disabled) { - return; - } - toggleMenu(); - }, + onClick: handleToggleMenu, }), }} error={error} @@ -249,7 +231,6 @@ const SingleAutocompleteSelectFieldComponent: React.FC {isOpen && (!!inputValue || !!choices.length) && ( diff --git a/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectFieldContent.tsx b/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectFieldContent.tsx index 73fece3d0..20ab3ccbf 100644 --- a/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectFieldContent.tsx +++ b/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectFieldContent.tsx @@ -69,7 +69,7 @@ const useStyles = makeStyles( ? theme.palette.grey[50] : theme.palette.grey[900], bottom: 0, - color: theme.palette.primary.main, + color: theme.palette.grey[500], display: "flex", height: 30, justifyContent: "center", diff --git a/src/components/SingleAutocompleteSelectField/styles.ts b/src/components/SingleAutocompleteSelectField/styles.ts new file mode 100644 index 000000000..20c7866c1 --- /dev/null +++ b/src/components/SingleAutocompleteSelectField/styles.ts @@ -0,0 +1,27 @@ +import { makeStyles } from "@saleor/macaw-ui"; + +export const useStyles = makeStyles( + theme => ({ + container: { + flexGrow: 1, + position: "relative", + }, + nakedInput: { + padding: theme.spacing(2, 0), + }, + adornment: { + color: theme.palette.saleor.main[3], + cursor: "pointer", + userSelect: "none", + "& svg": { + transition: theme.transitions.duration.shorter + "ms", + }, + }, + adornmentRotate: { + "& svg": { + transform: "rotate(180deg)", + }, + }, + }), + { name: "SingleAutocompleteSelectField" }, +); diff --git a/src/storybook/__snapshots__/Stories.test.ts.snap b/src/storybook/__snapshots__/Stories.test.ts.snap index 40c1a072c..520200683 100644 --- a/src/storybook/__snapshots__/Stories.test.ts.snap +++ b/src/storybook/__snapshots__/Stories.test.ts.snap @@ -127,12 +127,7 @@ exports[`Storyshots Attributes / Attributes default 1`] = ` value="" />