From a84389da13c9f8c00e6c502177877bd5226a115a Mon Sep 17 00:00:00 2001 From: Xiao Yijun Date: Tue, 16 Jul 2024 21:59:39 +0800 Subject: [PATCH] fix(experience): correct active state for input field (#6255) --- .../InputFields/InputField/index.tsx | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/packages/experience/src/components/InputFields/InputField/index.tsx b/packages/experience/src/components/InputFields/InputField/index.tsx index bdf5faf3c..78845f2b8 100644 --- a/packages/experience/src/components/InputFields/InputField/index.tsx +++ b/packages/experience/src/components/InputFields/InputField/index.tsx @@ -1,7 +1,15 @@ import { type Nullable } from '@silverhand/essentials'; import classNames from 'classnames'; -import type { HTMLProps, ReactElement, Ref } from 'react'; -import { forwardRef, cloneElement, useState, useImperativeHandle, useRef, useEffect } from 'react'; +import type { HTMLProps, ReactElement, Ref, AnimationEvent } from 'react'; +import { + forwardRef, + cloneElement, + useState, + useImperativeHandle, + useRef, + useEffect, + useCallback, +} from 'react'; import ErrorMessage from '@/components/ErrorMessage'; @@ -47,33 +55,25 @@ const InputField = ( const [isFocused, setIsFocused] = useState(false); const [hasValue, setHasValue] = useState(false); - const hasContent = - Boolean(isPrefixVisible) || - hasValue || - // Handle the case when this filed have a default value - Boolean(value); - - const isActive = hasContent || isFocused; useEffect(() => { - const inputDom = innerRef.current; - if (!inputDom) { - return; - } - /** - * Use a timeout to check if the input field has autofill value. - * Fix the issue that the input field doesn't have the active style when the autofill value is set. - * see https://github.com/facebook/react/issues/1159#issuecomment-1025423604 + * Should listen to the value prop to update the hasValue state. */ - const checkAutoFillTimeout = setTimeout(() => { - setHasValue(inputDom.matches('*:-webkit-autofill')); - }, 200); + setHasValue(Boolean(value)); + }, [value]); - return () => { - clearTimeout(checkAutoFillTimeout); - }; - }, [innerRef]); + /** + * Fix the issue that the input field doesn't have the active style when the autofill value is set. + * Modern browsers will trigger an animation event when the input field is autofilled. + */ + const handleAnimationStart = useCallback((event: AnimationEvent) => { + if (event.animationName === 'onautofillstart') { + setHasValue(true); + } + }, []); + + const isActive = Boolean(isPrefixVisible) || hasValue || isFocused; return (
@@ -97,6 +97,7 @@ const InputField = ( {...props} ref={innerRef} value={value} + onAnimationStart={handleAnimationStart} onFocus={(event) => { setIsFocused(true); return onFocus?.(event);