Skip to content

Commit 1e7ad04

Browse files
committed
fix(carbon): add helper text/errors where missing
1 parent 9aef2c2 commit 1e7ad04

File tree

9 files changed

+138
-106
lines changed

9 files changed

+138
-106
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
4+
import './helper-text-block.scss';
5+
6+
const HelperTextBlock = ({ helperText, errorText }) => {
7+
if (errorText) {
8+
return <div className="bx--form-requirement ddorg__carbon-error-helper-text">{errorText}</div>;
9+
}
10+
11+
if (helperText) {
12+
return <div className="bx--form__helper-text">{helperText}</div>;
13+
}
14+
15+
return null;
16+
};
17+
18+
HelperTextBlock.propTypes = {
19+
helperText: PropTypes.node,
20+
errorText: PropTypes.node
21+
};
22+
23+
export default HelperTextBlock;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.ddorg__carbon-error-helper-text {
2+
color: #da1e28;
3+
display: block;
4+
overflow: initial;
5+
}

packages/carbon-component-mapper/src/files/checkbox.js

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,35 @@ import { Checkbox as CarbonCheckbox, FormGroup } from 'carbon-components-react';
77

88
import WithDescription from '../common/with-description';
99
import prepareProps from '../common/prepare-props';
10+
import HelperTextBlock from '../common/helper-text-block';
1011

11-
const Wrapper = ({ label, description, children }) => (
12-
<FormGroup legendText={description ? <WithDescription labelText={label} description={description} /> : label}>{children}</FormGroup>
12+
const Wrapper = ({ label, description, children, helperText, error, showError }) => (
13+
<FormGroup legendText={description ? <WithDescription labelText={label} description={description} /> : label}>
14+
{children}
15+
<HelperTextBlock helperText={helperText} errorText={showError && error} />
16+
</FormGroup>
1317
);
1418

1519
Wrapper.propTypes = {
1620
label: PropTypes.node,
1721
children: PropTypes.node,
18-
description: PropTypes.node
22+
description: PropTypes.node,
23+
helperText: PropTypes.node,
24+
error: PropTypes.node,
25+
showError: PropTypes.bool
1926
};
2027

2128
const SingleCheckbox = (props) => {
22-
const { input, ...rest } = useFieldApi(prepareProps({ ...props, type: 'checkbox' }));
29+
const { input, meta, validateOnMount, helperText, ...rest } = useFieldApi(prepareProps({ ...props, type: 'checkbox' }));
2330

24-
return <CarbonCheckbox {...input} id={input.name} {...rest} />;
31+
const invalid = (meta.touched || validateOnMount) && meta.error;
32+
33+
return (
34+
<div>
35+
<CarbonCheckbox {...input} id={input.name} {...rest} />
36+
<HelperTextBlock helperText={helperText} errorText={invalid} />
37+
</div>
38+
);
2539
};
2640

2741
const SingleCheckboxInCommon = ({ label, isDisabled, id, ...props }) => <CarbonCheckbox id={id} labelText={label} disabled={isDisabled} />;

packages/carbon-component-mapper/src/files/date-picker.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,20 @@ import { useFieldApi } from '@data-driven-forms/react-form-renderer';
55
import { DatePicker as CarbonDatePicker, DatePickerInput } from 'carbon-components-react';
66

77
import prepareProps from '../common/prepare-props';
8+
import HelperTextBlock from '../common/helper-text-block';
89

910
const DatePicker = (props) => {
10-
const { input, datePickerType, meta, DatePickerProps, validateOnMount, ...rest } = useFieldApi(prepareProps(props));
11+
const { input, datePickerType, meta, DatePickerProps, validateOnMount, helperText, ...rest } = useFieldApi(prepareProps(props));
1112

1213
const invalid = (meta.touched || validateOnMount) && meta.error;
1314

1415
return (
15-
<CarbonDatePicker {...input} datePickerType={datePickerType} {...DatePickerProps}>
16-
<DatePickerInput id={input.name} invalid={Boolean(invalid)} invalidText={invalid ? invalid : ''} {...rest} />
17-
</CarbonDatePicker>
16+
<div>
17+
<CarbonDatePicker {...input} datePickerType={datePickerType} {...DatePickerProps}>
18+
<DatePickerInput id={input.name} invalid={Boolean(invalid)} invalidText={invalid ? invalid : ''} {...rest} />
19+
</CarbonDatePicker>
20+
<HelperTextBlock helperText={!invalid && helperText} />
21+
</div>
1822
);
1923
};
2024

packages/carbon-component-mapper/src/files/radio.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,14 @@ import { useFieldApi } from '@data-driven-forms/react-form-renderer';
55
import { FormGroup, RadioButtonGroup, RadioButton } from 'carbon-components-react';
66

77
import prepareProps from '../common/prepare-props';
8+
import HelperTextBlock from '../common/helper-text-block';
89

910
const Radio = (props) => {
10-
const { labelText, disabled, input, options, FormGroupProps, ...rest } = useFieldApi(prepareProps({ type: 'radio', ...props }));
11+
const { labelText, disabled, input, options, FormGroupProps, helperText, meta, validateOnMount, ...rest } = useFieldApi(
12+
prepareProps({ type: 'radio', ...props })
13+
);
14+
15+
const invalid = (meta.touched || validateOnMount) && meta.error;
1116

1217
return (
1318
<FormGroup legendText={labelText} {...FormGroupProps}>
@@ -16,6 +21,7 @@ const Radio = (props) => {
1621
<RadioButton key={option.value} disabled={disabled} labelText={option.label} value={option.value} {...option} />
1722
))}
1823
</RadioButtonGroup>
24+
<HelperTextBlock helperText={helperText} errorText={invalid} />
1925
</FormGroup>
2026
);
2127
};

packages/carbon-component-mapper/src/files/slider.js

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,28 @@ import { useFieldApi } from '@data-driven-forms/react-form-renderer';
55
import { Slider as CarbonSlider } from 'carbon-components-react';
66

77
import prepareProps from '../common/prepare-props';
8+
import HelperTextBlock from '../common/helper-text-block';
89

910
const Slider = (props) => {
10-
const { input, meta, isRequired, validateOnMount, ...rest } = useFieldApi(prepareProps(props));
11+
const { input, meta, isRequired, validateOnMount, helperText, ...rest } = useFieldApi(prepareProps(props));
1112

1213
const invalid = (meta.touched || validateOnMount) && meta.error;
1314

1415
return (
15-
<CarbonSlider
16-
{...input}
17-
value={Number(input.value) || 0}
18-
key={input.name}
19-
id={input.name}
20-
invalid={Boolean(invalid)}
21-
min={0}
22-
max={100}
23-
required={isRequired}
24-
{...rest}
25-
/>
16+
<div>
17+
<CarbonSlider
18+
{...input}
19+
value={Number(input.value) || 0}
20+
key={input.name}
21+
id={input.name}
22+
invalid={Boolean(invalid)}
23+
min={0}
24+
max={100}
25+
required={isRequired}
26+
{...rest}
27+
/>
28+
<HelperTextBlock helperText={helperText} errorText={invalid} />
29+
</div>
2630
);
2731
};
2832

packages/carbon-component-mapper/src/files/switch.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,19 @@ import { useFieldApi } from '@data-driven-forms/react-form-renderer';
55
import { Toggle } from 'carbon-components-react';
66

77
import prepareProps from '../common/prepare-props';
8+
import HelperTextBlock from '../common/helper-text-block';
89

910
const Switch = (props) => {
10-
const { input, meta, onText, offText, ...rest } = useFieldApi(prepareProps(props));
11+
const { input, meta, onText, offText, validateOnMount, helperText, ...rest } = useFieldApi(prepareProps(props));
1112

12-
return <Toggle {...input} key={input.name} id={input.name} labelA={offText} labelB={onText} {...rest} />;
13+
const invalid = (meta.touched || validateOnMount) && meta.error;
14+
15+
return (
16+
<div>
17+
<Toggle {...input} key={input.name} id={input.name} labelA={offText} labelB={onText} {...rest} />
18+
<HelperTextBlock helperText={helperText} errorText={invalid} />
19+
</div>
20+
);
1321
};
1422

1523
Switch.propTypes = {

packages/carbon-component-mapper/src/files/time-picker.js

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ import { useFieldApi } from '@data-driven-forms/react-form-renderer';
55
import { TimePicker as CarbonTimePicker, TimePickerSelect, SelectItem } from 'carbon-components-react';
66

77
import prepareProps from '../common/prepare-props';
8+
import HelperTextBlock from '../common/helper-text-block';
89

910
const TimePicker = (props) => {
10-
const { input, meta, twelveHoursFormat, timezones, validateOnMount, ...rest } = useFieldApi(prepareProps(props));
11+
const { input, meta, twelveHoursFormat, timezones, validateOnMount, helperText, ...rest } = useFieldApi(prepareProps(props));
1112

1213
const [timezone, selectTimezone] = useState(timezones ? timezones[0]?.value : '');
1314
const [format, selectFormat] = useState('AM');
@@ -63,30 +64,37 @@ const TimePicker = (props) => {
6364
}, [timezone, format]);
6465

6566
return (
66-
<CarbonTimePicker
67-
{...input}
68-
value={finalValue}
69-
onBlur={enhnancedOnBlur}
70-
key={input.name}
71-
id={input.name}
72-
invalid={Boolean(invalid)}
73-
invalidText={invalid || ''}
74-
{...rest}
75-
>
76-
{twelveHoursFormat && (
77-
<TimePickerSelect labelText="Period" id={`${rest.id || input.name}-12h`} onChange={({ target: { value } }) => selectFormat(value)}>
78-
<SelectItem value="AM" text="AM" />
79-
<SelectItem value="PM" text="PM" />
80-
</TimePickerSelect>
81-
)}
82-
{timezones && (
83-
<TimePickerSelect labelText="Timezone" id={`${rest.id || input.name}-timezones`} onChange={({ target: { value } }) => selectTimezone(value)}>
84-
{timezones.map(({ showAs, ...tz }) => (
85-
<SelectItem key={tz.value} text={tz.label} {...tz} />
86-
))}
87-
</TimePickerSelect>
88-
)}
89-
</CarbonTimePicker>
67+
<div>
68+
<CarbonTimePicker
69+
{...input}
70+
value={finalValue}
71+
onBlur={enhnancedOnBlur}
72+
key={input.name}
73+
id={input.name}
74+
invalid={Boolean(invalid)}
75+
invalidText={invalid || ''}
76+
{...rest}
77+
>
78+
{twelveHoursFormat && (
79+
<TimePickerSelect labelText="Period" id={`${rest.id || input.name}-12h`} onChange={({ target: { value } }) => selectFormat(value)}>
80+
<SelectItem value="AM" text="AM" />
81+
<SelectItem value="PM" text="PM" />
82+
</TimePickerSelect>
83+
)}
84+
{timezones && (
85+
<TimePickerSelect
86+
labelText="Timezone"
87+
id={`${rest.id || input.name}-timezones`}
88+
onChange={({ target: { value } }) => selectTimezone(value)}
89+
>
90+
{timezones.map(({ showAs, ...tz }) => (
91+
<SelectItem key={tz.value} text={tz.label} {...tz} />
92+
))}
93+
</TimePickerSelect>
94+
)}
95+
</CarbonTimePicker>
96+
<HelperTextBlock helperText={!invalid && helperText} />
97+
</div>
9098
);
9199
};
92100

packages/carbon-component-mapper/src/tests/components.test.js

Lines changed: 17 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,6 @@ describe('component tests', () => {
8181
});
8282

8383
it('renders with error', () => {
84-
if ([componentTypes.RADIO, componentTypes.SWITCH, componentTypes.CHECKBOX].includes(component)) {
85-
// 'skipped because this component does not support this';
86-
return;
87-
}
88-
8984
const errorField = {
9085
...field,
9186
validate: [{ type: validatorTypes.REQUIRED }]
@@ -95,26 +90,15 @@ describe('component tests', () => {
9590

9691
if (wrapper.find('#field-name-error-msg').length) {
9792
expect(wrapper.find('#field-name-error-msg').text()).toEqual(errorText);
93+
expect(wrapper.find('[invalid=true]').length).toBeGreaterThanOrEqual(1);
9894
}
9995

100-
expect(wrapper.find('[invalid=true]').length).toBeGreaterThanOrEqual(1);
96+
if (wrapper.find('.ddorg__carbon-error-helper-text').length) {
97+
expect(wrapper.find('.ddorg__carbon-error-helper-text').text()).toEqual(errorText);
98+
}
10199
});
102100

103101
it('renders with helperText', () => {
104-
if (
105-
[
106-
componentTypes.RADIO,
107-
componentTypes.SWITCH,
108-
componentTypes.CHECKBOX,
109-
componentTypes.DATE_PICKER,
110-
componentTypes.TIME_PICKER,
111-
componentTypes.SLIDER
112-
].includes(component)
113-
) {
114-
// 'skipped because this component does not support this';
115-
return;
116-
}
117-
118102
const helpertextField = {
119103
...field,
120104
helperText
@@ -143,60 +127,36 @@ describe('component tests', () => {
143127
const descriptionField = {
144128
...field,
145129
description,
146-
...(![
147-
componentTypes.RADIO,
148-
componentTypes.SWITCH,
149-
componentTypes.CHECKBOX,
150-
componentTypes.DATE_PICKER,
151-
componentTypes.TIME_PICKER,
152-
componentTypes.SLIDER
153-
].includes(component)
154-
? { helperText }
155-
: {})
130+
helperText
156131
};
157132
const wrapper = mount(<RendererWrapper schema={{ fields: [descriptionField] }} />);
158133

159134
expect(wrapper.find(WithDescription)).toHaveLength(1);
160135

161-
if (
162-
![
163-
componentTypes.RADIO,
164-
componentTypes.SWITCH,
165-
componentTypes.CHECKBOX,
166-
componentTypes.DATE_PICKER,
167-
componentTypes.TIME_PICKER,
168-
componentTypes.SLIDER
169-
].includes(component)
170-
) {
171-
expect(
172-
wrapper
173-
.find('.bx--form__helper-text')
174-
.last()
175-
.text()
176-
).toEqual(helperText);
177-
}
136+
expect(
137+
wrapper
138+
.find('.bx--form__helper-text')
139+
.last()
140+
.text()
141+
).toEqual(helperText);
178142
});
179143

180144
it('renders with error and helperText', () => {
181145
const errorFields = {
182146
...field,
183-
...(![
184-
componentTypes.RADIO,
185-
componentTypes.SWITCH,
186-
componentTypes.CHECKBOX,
187-
componentTypes.DATE_PICKER,
188-
componentTypes.TIME_PICKER,
189-
componentTypes.SLIDER
190-
].includes(component)
191-
? { helperText }
192-
: {}),
147+
helperText,
193148
validate: [{ type: validatorTypes.REQUIRED }]
194149
};
195150
const wrapper = mount(<RendererWrapper schema={{ fields: [errorFields] }} />);
196151
wrapper.find('form').simulate('submit');
197152

198153
if (wrapper.find('#field-name-error-msg').length) {
199154
expect(wrapper.find('#field-name-error-msg').text()).toEqual(errorText);
155+
expect(wrapper.find('[invalid=true]').length).toBeGreaterThanOrEqual(1);
156+
}
157+
158+
if (wrapper.find('.ddorg__carbon-error-helper-text').length) {
159+
expect(wrapper.find('.ddorg__carbon-error-helper-text').text()).toEqual(errorText);
200160
}
201161

202162
expect(wrapper.find('.bx--form__helper-text')).toHaveLength(0);

0 commit comments

Comments
 (0)