Skip to content

Commit ca57ca6

Browse files
committed
feat: enhance FormFieldRenderer with focus handling and help text feedback
1 parent d2a5da9 commit ca57ca6

1 file changed

Lines changed: 28 additions & 22 deletions

File tree

src/field-renderer/FieldRenderer.jsx

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,42 @@
1-
import React from 'react';
1+
import React, { useState } from 'react';
22

3-
import { Form, Icon } from '@openedx/paragon';
3+
import { Form, Icon, TransitionReplace } from '@openedx/paragon';
44
import { ExpandMore } from '@openedx/paragon/icons';
55
import PropTypes from 'prop-types';
66

77
const FormFieldRenderer = (props) => {
8+
const [hasFocus, setHasFocus] = useState(false);
89
let formField = null;
910
const {
1011
className, errorMessage, fieldData, onChangeHandler, isRequired, value,
1112
} = props;
1213

1314
const handleFocus = (e) => {
15+
setHasFocus(true);
1416
if (props.handleFocus) { props.handleFocus(e); }
1517
};
1618

1719
const handleOnBlur = (e) => {
20+
setHasFocus(false);
1821
if (props.handleBlur) { props.handleBlur(e); }
1922
};
2023

24+
const helpTextFeedback = (
25+
<TransitionReplace>
26+
{hasFocus && fieldData.instructions ? (
27+
<Form.Control.Feedback type="default" key="help-text" className="d-block form-text-size">
28+
{fieldData.instructions}
29+
</Form.Control.Feedback>
30+
) : <div key="empty" />}
31+
</TransitionReplace>
32+
);
33+
34+
const errorFeedback = isRequired && errorMessage ? (
35+
<Form.Control.Feedback id={`${fieldData.name}-error`} type="invalid" className="form-text-size" hasIcon={false}>
36+
{errorMessage}
37+
</Form.Control.Feedback>
38+
) : null;
39+
2140
switch (fieldData.type) {
2241
case 'select': {
2342
if (!fieldData.options) {
@@ -42,11 +61,7 @@ const FormFieldRenderer = (props) => {
4261
<option className="data-hj-suppress" key={option[0]} value={option[0]}>{option[1]}</option>
4362
))}
4463
</Form.Control>
45-
{isRequired && errorMessage && (
46-
<Form.Control.Feedback id={`${fieldData.name}-error`} type="invalid" className="form-text-size" hasIcon={false}>
47-
{errorMessage}
48-
</Form.Control.Feedback>
49-
)}
64+
{errorFeedback}
5065
</Form.Group>
5166
);
5267
break;
@@ -66,11 +81,8 @@ const FormFieldRenderer = (props) => {
6681
onBlur={handleOnBlur}
6782
onFocus={handleFocus}
6883
/>
69-
{isRequired && errorMessage && (
70-
<Form.Control.Feedback id={`${fieldData.name}-error`} type="invalid" className="form-text-size" hasIcon={false}>
71-
{errorMessage}
72-
</Form.Control.Feedback>
73-
)}
84+
{helpTextFeedback}
85+
{errorFeedback}
7486
</Form.Group>
7587
);
7688
break;
@@ -89,11 +101,8 @@ const FormFieldRenderer = (props) => {
89101
onBlur={handleOnBlur}
90102
onFocus={handleFocus}
91103
/>
92-
{isRequired && errorMessage && (
93-
<Form.Control.Feedback id={`${fieldData.name}-error`} type="invalid" className="form-text-size" hasIcon={false}>
94-
{errorMessage}
95-
</Form.Control.Feedback>
96-
)}
104+
{helpTextFeedback}
105+
{errorFeedback}
97106
</Form.Group>
98107
);
99108
break;
@@ -114,11 +123,7 @@ const FormFieldRenderer = (props) => {
114123
>
115124
{fieldData.label}
116125
</Form.Checkbox>
117-
{isRequired && errorMessage && (
118-
<Form.Control.Feedback id={`${fieldData.name}-error`} type="invalid" className="form-text-size" hasIcon={false}>
119-
{errorMessage}
120-
</Form.Control.Feedback>
121-
)}
126+
{errorFeedback}
122127
</Form.Group>
123128
);
124129
break;
@@ -145,6 +150,7 @@ FormFieldRenderer.propTypes = {
145150
label: PropTypes.string,
146151
name: PropTypes.string,
147152
placeholder: PropTypes.string,
153+
instructions: PropTypes.string,
148154
options: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.string)),
149155
}).isRequired,
150156
onChangeHandler: PropTypes.func.isRequired,

0 commit comments

Comments
 (0)