From 5771dc0172e7fd771aec7bdc95272e957b7eea8d Mon Sep 17 00:00:00 2001 From: Vasilica Olariu Date: Tue, 27 Sep 2022 17:14:14 +0300 Subject: [PATCH 1/2] TCA-468 TCA-466 - fix issues with input error message --- client/src/assets/icons/warning.tsx | 44 +++++++++ .../src/components/formHelpers/form-field.css | 26 ++++++ .../components/formHelpers/form-fields.tsx | 89 +++++++++++-------- client/src/components/layouts/variables.css | 2 + 4 files changed, 125 insertions(+), 36 deletions(-) create mode 100644 client/src/assets/icons/warning.tsx create mode 100644 client/src/components/formHelpers/form-field.css diff --git a/client/src/assets/icons/warning.tsx b/client/src/assets/icons/warning.tsx new file mode 100644 index 00000000000000..6e8dc2e42cd585 --- /dev/null +++ b/client/src/assets/icons/warning.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +function Warning( + props: JSX.IntrinsicAttributes & React.SVGProps +): JSX.Element { + const { t } = useTranslation(); + + return ( + + + {t('icons.fail')} + + + + ); +} + +Warning.displayName = 'Warning'; + +export default Warning; diff --git a/client/src/components/formHelpers/form-field.css b/client/src/components/formHelpers/form-field.css new file mode 100644 index 00000000000000..80e702211877c8 --- /dev/null +++ b/client/src/components/formHelpers/form-field.css @@ -0,0 +1,26 @@ +.input-help-box { + max-width: 320px; + margin-top: -11px; +} + +.input-message { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + font-size: 12px; + line-height: 14px; + display: flex; + align-items: center; +} + +.input-message > svg { + margin-right: 7px; +} + +.input-message.is-error { + color: var(--tc-red-100); +} + +.input-message.is-warn { + color: var(--tc-legacy-120); +} diff --git a/client/src/components/formHelpers/form-fields.tsx b/client/src/components/formHelpers/form-fields.tsx index 6917d846d98e46..60f460364f62f7 100644 --- a/client/src/components/formHelpers/form-fields.tsx +++ b/client/src/components/formHelpers/form-fields.tsx @@ -5,11 +5,12 @@ import { FormGroup, HelpBlock } from '@freecodecamp/react-bootstrap'; -import { kebabCase } from 'lodash-es'; +import { kebabCase, set } from 'lodash-es'; import normalizeUrl from 'normalize-url'; -import React from 'react'; +import React, { Fragment, useState } from 'react'; import { Field } from 'react-final-form'; import { useTranslation } from 'react-i18next'; +import Warning from '../../assets/icons/warning'; import { FormOptions } from './form'; import { editorValidator, @@ -18,6 +19,7 @@ import { fCCValidator, httpValidator } from './form-validators'; +import './form-field.css'; type FormFieldsProps = { formFields: { name: string; label: string }[]; @@ -36,6 +38,10 @@ function FormFields(props: FormFieldsProps): JSX.Element { isLocalLinkAllowed = false } = options; + const [blured, setBlured] = useState([]); + const markAsBlured = (index: number) => + setBlured(prevState => set([...prevState], index, true)); + const nullOrWarning = ( value: string, error: unknown, @@ -59,14 +65,21 @@ function FormFields(props: FormFieldsProps): JSX.Element { const message: string = (error || validationError || validationWarning) as string; + + const hasError = error || validationError; + const classNames = [ + 'input-message', + hasError && 'is-error', + !hasError && 'is-warn' + ] + .filter(Boolean) + .join(' '); return message ? ( - - + +
+ {message} - +
) : null; }; @@ -74,7 +87,7 @@ function FormFields(props: FormFieldsProps): JSX.Element { <> {formFields .filter(formField => !ignored.includes(formField.name)) - .map(({ name, label }) => ( + .map(({ name, label }, i) => ( // TODO: verify if the value is always a string {({ input: { value, onChange }, meta: { pristine, error } }) => { @@ -84,33 +97,37 @@ function FormFields(props: FormFieldsProps): JSX.Element { name in placeholders ? placeholders[name] : ''; const isURL = types[name] === 'url'; return ( - - {type === 'hidden' ? null : ( - - {label} - {required.includes(name) && ( - * - )} - - )} - - {nullOrWarning( - value as string, - !pristine && error, - isURL, - name - )} - + + + {type === 'hidden' ? null : ( + + {label} + {required.includes(name) && ( + * + )} + + )} + markAsBlured(i)} + /> + + {blured[i] && + nullOrWarning( + value as string, + !pristine && error, + isURL, + name + )} + ); }} diff --git a/client/src/components/layouts/variables.css b/client/src/components/layouts/variables.css index 2d757df343facc..5f16ffdc49c998 100644 --- a/client/src/components/layouts/variables.css +++ b/client/src/components/layouts/variables.css @@ -45,6 +45,8 @@ --tc-blue-140: #16679a; --tc-blue-25: #bae1f9; --tc-blue-10: #eaf6fd; + --tc-red-100: #ef476f; + --tc-legacy-120: #f46500; } .dark-palette { From 4fef172b49b7ff0abd41bb7d92a4a4347d9da672 Mon Sep 17 00:00:00 2001 From: Vasilica Olariu Date: Wed, 28 Sep 2022 11:38:53 +0300 Subject: [PATCH 2/2] lint fixes --- client/src/components/formHelpers/form-fields.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/client/src/components/formHelpers/form-fields.tsx b/client/src/components/formHelpers/form-fields.tsx index 60f460364f62f7..51b0f0fc09c957 100644 --- a/client/src/components/formHelpers/form-fields.tsx +++ b/client/src/components/formHelpers/form-fields.tsx @@ -1,5 +1,4 @@ import { - Alert, ControlLabel, FormControl, FormGroup, @@ -9,7 +8,6 @@ import { kebabCase, set } from 'lodash-es'; import normalizeUrl from 'normalize-url'; import React, { Fragment, useState } from 'react'; import { Field } from 'react-final-form'; -import { useTranslation } from 'react-i18next'; import Warning from '../../assets/icons/warning'; import { FormOptions } from './form'; import { @@ -27,7 +25,6 @@ type FormFieldsProps = { }; function FormFields(props: FormFieldsProps): JSX.Element { - const { t } = useTranslation(); const { formFields, options = {} }: FormFieldsProps = props; const { ignored = [],