Skip to content

Commit eb3cb5d

Browse files
author
Dave Ferris
committed
UIDS-16 updates
1 parent 207596b commit eb3cb5d

File tree

12 files changed

+186
-581
lines changed

12 files changed

+186
-581
lines changed

spec/__snapshots__/Storyshots.test.js.snap

Lines changed: 118 additions & 364 deletions
Large diffs are not rendered by default.

src/Form/Form.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import './Form.scss';
77
export default function Form(props) {
88
return (
99
<form
10-
className={classNames('Form', props.inline ? 'inline' : '')}
10+
className={classNames('Form', { 'Form--inline': props.inline })}
1111
id={props.id}
1212
onSubmit={props.onSubmit}
1313
>

src/Form/Form.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
.Form {
2-
&.inline {
2+
&--inline {
33
.FormGroup {
44
align-items: center;
55
display: flex;
66
flex-direction: row;
77

8-
.FormControl {
8+
input, textarea {
99
flex-basis: 25%;
1010
min-width: 12rem;
1111
order: 1;

src/FormControl/FormControl.jsx

Lines changed: 0 additions & 76 deletions
This file was deleted.

src/FormControl/FormControl.scss

Lines changed: 0 additions & 15 deletions
This file was deleted.

src/FormGroup/FormGroup.jsx

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,64 +2,72 @@ import React from 'react';
22
import PropTypes from 'prop-types';
33
import classNames from 'classnames';
44

5-
import FormControl from '../FormControl/FormControl';
65
import FormLabel from '../FormLabel/FormLabel';
76

87
import './FormGroup.scss';
98

9+
function renderErrors(errors) {
10+
if (typeof errors === 'string') {
11+
return errors;
12+
}
13+
14+
return (
15+
<ol className="invalid-feedback__list">
16+
{
17+
// eslint-disable-next-line react/no-array-index-key
18+
errors.map((e, idx) => <li key={idx}>{e}</li>)
19+
}
20+
</ol>
21+
);
22+
}
23+
1024
export default function FormGroup(props) {
25+
const { errors, inputKey } = props;
26+
const hasErrors = errors[inputKey] && errors[inputKey].length > 0;
27+
1128
return (
12-
<div className={classNames('FormGroup', props.className)} id={props.id}>
29+
<div className={classNames('FormGroup', props.className, { 'FormGroup--is-invalid': hasErrors })} id={props.id}>
1330
{props.label && (
1431
<FormLabel
1532
className={props.labelClassName}
1633
labelHtmlFor={props.labelHtmlFor}
17-
legend={props.legend}
1834
required={props.required}
1935
text={props.label}
2036
/>
2137
)}
2238

23-
<FormControl
24-
description={props.description}
25-
displayErrorText={props.displayErrorText}
26-
errors={props.errors}
27-
inputClassName={props.inputClassName}
28-
inputKey={props.inputKey}
29-
>
30-
{props.children}
31-
</FormControl>
39+
{props.children}
40+
41+
{props.displayErrorText && hasErrors && (
42+
<div className="invalid-feedback">
43+
{renderErrors(errors[inputKey])}
44+
</div>
45+
)}
3246
</div>
3347
);
3448
}
3549

3650
FormGroup.propTypes = {
3751
children: PropTypes.node,
3852
className: PropTypes.string,
39-
description: PropTypes.string,
4053
displayErrorText: PropTypes.bool,
4154
errors: PropTypes.object,
4255
id: PropTypes.string.isRequired,
43-
inputClassName: PropTypes.string,
4456
inputKey: PropTypes.string,
4557
label: PropTypes.string,
4658
labelClassName: PropTypes.string,
4759
labelHtmlFor: PropTypes.string,
48-
legend: PropTypes.node,
4960
required: PropTypes.bool,
5061
};
5162

5263
FormGroup.defaultProps = {
5364
children: undefined,
5465
className: '',
55-
description: '',
5666
displayErrorText: true,
5767
errors: {},
58-
inputClassName: '',
5968
inputKey: null,
6069
label: '',
6170
labelClassName: '',
6271
labelHtmlFor: '',
63-
legend: undefined,
6472
required: false,
6573
};

src/FormGroup/FormGroup.scss

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
@import '../../scss/theme';
2+
13
.FormGroup {
24
margin: 1rem 0 0.5rem;
5+
6+
&--is-invalid {
7+
input, textarea {
8+
border-color: $ux-red;
9+
}
10+
}
11+
12+
.invalid-feedback {
13+
color: $ux-red;
14+
display: block;
15+
font-size: 100%;
16+
17+
&__list {
18+
@include ui-remove-list-styles();
19+
}
20+
}
321
}

src/FormLabel/FormLabel.jsx

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,30 @@
11
import React from 'react';
22
import PropTypes from 'prop-types';
3-
import classNames from 'classnames';
43

54
import './FormLabel.scss';
65

76
export default function FormLabel(props) {
87
const {
9-
className,
108
labelHtmlFor,
11-
legend,
129
required,
1310
text,
1411
} = props;
1512

16-
const label = labelHtmlFor ? <label htmlFor={labelHtmlFor}>{text}</label> : <span>{text}</span>;
17-
1813
return (
19-
<div className={classNames('FormLabel', className)}>
20-
{label}
14+
<label className="FormLabel" htmlFor={labelHtmlFor}>
15+
{text}
2116
{required && <span className="helper-text">&nbsp;(required)</span>}
22-
{legend}
23-
</div>
17+
</label>
2418
);
2519
}
2620

2721
FormLabel.propTypes = {
28-
className: PropTypes.string,
2922
labelHtmlFor: PropTypes.string,
30-
legend: PropTypes.node,
3123
required: PropTypes.bool,
3224
text: PropTypes.string.isRequired,
3325
};
3426

3527
FormLabel.defaultProps = {
36-
className: '',
3728
labelHtmlFor: '',
38-
legend: undefined,
3929
required: false,
4030
};

src/index.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
import Card from './Card/Card';
22
import Form from './Form/Form';
3-
import FormControl from './FormControl/FormControl';
43
import FormGroup from './FormGroup/FormGroup';
54
import FormLabel from './FormLabel/FormLabel';
65
import Pill from './Pill/Pill';
76

87
export {
98
Card,
109
Form,
11-
FormControl,
1210
FormGroup,
1311
FormLabel,
1412
Pill,

stories/Form.stories.jsx

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { withA11y } from '@storybook/addon-a11y';
33
import { action } from '@storybook/addon-actions';
44

55
import Form from '../src/Form/Form';
6-
import FormControl from '../src/FormControl/FormControl';
76
import FormGroup from '../src/FormGroup/FormGroup';
87

98
const withPadding = (story) => <div style={{ padding: '1rem' }}>{story()}</div>;
@@ -22,23 +21,22 @@ const onSubmit = (event) => {
2221
export const Default = () => (
2322
<Form id="form" onSubmit={onSubmit}>
2423
<FormGroup label="First name" labelHtmlFor="first-name">
25-
<FormControl description="Enter your first name">
26-
<input className="form-control" id="first-name" type="text" />
27-
</FormControl>
24+
<input className="form-control" id="first-name" type="text" />
2825
</FormGroup>
2926
<FormGroup label="Last name" labelHtmlFor="last-name" required>
30-
<FormControl description="Enter your last name">
31-
<input className="form-control" id="last-name" type="text" />
32-
</FormControl>
27+
<input className="form-control" id="last-name" type="text" />
3328
</FormGroup>
3429
<FormGroup label="Email" labelHtmlFor="email">
35-
<FormControl
36-
description="Enter your email address"
37-
errors={{ email: 'invalid email' }}
38-
inputKey="email"
39-
>
40-
<input className="form-control" id="email" type="text" />
41-
</FormControl>
30+
<input className="form-control" id="email" type="text" />
31+
</FormGroup>
32+
<FormGroup
33+
errors={{ phone: 'Invalid phone number' }}
34+
inputKey="phone"
35+
label="Phone"
36+
labelHtmlFor="phone"
37+
required
38+
>
39+
<input className="form-control" id="phone" type="text" />
4240
</FormGroup>
4341
<button className="btn btn-primary" type="submit">Save</button>
4442
</Form>
@@ -47,14 +45,13 @@ export const Default = () => (
4745
export const Inline = () => (
4846
<Form id="form" inline onSubmit={onSubmit}>
4947
<FormGroup label="First name" labelHtmlFor="first-name">
50-
<FormControl description="Enter your first name">
51-
<input className="form-control" id="first-name" type="text" />
52-
</FormControl>
48+
<input className="form-control" id="first-name" type="text" />
5349
</FormGroup>
5450
<FormGroup label="Last name" labelHtmlFor="last-name" required>
55-
<FormControl description="Enter your last name">
56-
<input className="form-control" id="last-name" type="text" />
57-
</FormControl>
51+
<input className="form-control" id="last-name" type="text" />
52+
</FormGroup>
53+
<FormGroup label="Description" labelHtmlFor="description">
54+
<textarea className="form-control" id="description" type="text" />
5855
</FormGroup>
5956
<button className="btn btn-primary" type="submit">Save</button>
6057
</Form>

0 commit comments

Comments
 (0)