From dffe163cfe31c1b9bac050a7ee2000c90444189e Mon Sep 17 00:00:00 2001 From: ITurres Date: Mon, 11 Mar 2024 00:45:45 -0300 Subject: [PATCH] Refactor: Enhance 'ContactForm' accessibility, Fix form focus and more - The new 'showSubmitButton' local state will be used to conditionally render the submit button. - Added label elements to all inputs. - With the addition of label elements, now in 'setInputStyle' we need to access the second 'nextSibling' element to access the next input after that input's label. - Removed 'setSubmitButtonStyle' function since now the styles will be applied conditionally in the component class name. - Without the 'setSubmitButtonStyle' function, now at the 'validateInput' function we now will style and show the button by toggling the 'showSubmitButton' state based on the validity of all inputs. --- src/components/UI/ContactForm.tsx | 116 ++++++++++++++++++------------ 1 file changed, 70 insertions(+), 46 deletions(-) diff --git a/src/components/UI/ContactForm.tsx b/src/components/UI/ContactForm.tsx index 2803280..5fea1ac 100644 --- a/src/components/UI/ContactForm.tsx +++ b/src/components/UI/ContactForm.tsx @@ -17,7 +17,9 @@ const ContactForm: React.FC = () => { // * sessionStorage.getItem('formContent')! is not null. ); + // * This state is to disable the submit button after the form is submitted. const [formSubmittedStatus, setFormSubmittedStatus] = useState(false); + const [showSubmitButton, setShowSubmitButton] = useState(false); const actionURL = process.env.REACT_APP_FORM_ACTION_URL; @@ -54,8 +56,14 @@ const ContactForm: React.FC = () => { ) => { if (isValid) { inputDomElement.classList.remove('invalid'); - if (inputDomElement.nextSibling instanceof HTMLElement) { - inputDomElement.nextSibling.classList.add('show'); + + // * If the input is valid, remove invalid class, add show class to next + // * input after label, and add valid class. + // ! Note: This method of accessing the next input after the label may not + // ! be the most robust. + const inputElementAfterLabelElement = inputDomElement.nextSibling?.nextSibling; + if (inputElementAfterLabelElement instanceof HTMLElement) { + inputElementAfterLabelElement.classList.add('show'); } inputDomElement.classList.add('valid'); } else { @@ -64,28 +72,26 @@ const ContactForm: React.FC = () => { } }; - const setSubmitButtonStyle = (isValid: boolean) => { - if (isValid) { - $submitButton.current?.classList.remove('invalid'); - $submitButton.current?.classList.add('valid'); - } else { - $submitButton.current?.classList.remove('valid'); - $submitButton.current?.classList.add('invalid'); - } - }; - - const validateInput = useCallback((input: any, regex: RegExp) => { - const inputKey = input.obj.current?.name as keyof typeof inputs; - const isValid = regex.test(input.obj.current?.value || ''); + const validateInput = useCallback( + (input: any, regex: RegExp) => { + const inputKey = input.obj.current?.name as keyof typeof inputs; + const isValid = regex.test(input.obj.current?.value || ''); - inputs[inputKey].validated = isValid; - setInputStyle(input.obj.current, isValid); + inputs[inputKey].validated = isValid; + setInputStyle(input.obj.current, isValid); - // * set the submit button style based on the validity of all inputs. - setSubmitButtonStyle( - Object.values(inputs).every((inputObj) => inputObj.validated), - ); - }, [inputs]); + // * set the submit button style based on the validity of all inputs. + const areAllValidInputs = Object.values(inputs).every( + (inputObj) => inputObj.validated, + ); + if (areAllValidInputs) { + setShowSubmitButton(true); + } else { + setShowSubmitButton(false); + } + }, + [inputs], + ); useEffect(() => { if (formContent) { @@ -93,16 +99,19 @@ const ContactForm: React.FC = () => { } }, [formContent]); - const updateFormContent = useCallback((input: any) => () => { - const inputKey = input.obj.current?.name as keyof typeof inputs; + const updateFormContent = useCallback( + (input: any) => () => { + const inputKey = input.obj.current?.name as keyof typeof inputs; - setFormContent((previousFormContent: any) => { - const currentFormContent = { ...previousFormContent }; - currentFormContent[inputKey] = input.obj.current?.value; + setFormContent((previousFormContent: any) => { + const currentFormContent = { ...previousFormContent }; + currentFormContent[inputKey] = input.obj.current?.value; - return currentFormContent; - }); - }, []); + return currentFormContent; + }); + }, + [], + ); useEffect(() => { Object.values(inputs).forEach((input) => { @@ -236,7 +245,10 @@ const ContactForm: React.FC = () => { ref={$form} onSubmit={handleSubmission} > + {/* eslint-disable jsx-a11y/label-has-associated-control */} + { required /> + { required /> + { required /> +