Skip to content

Commit d4ec7ee

Browse files
committed
Added Molecules SelectFormField and TextAreaFormField
1 parent 2a3811e commit d4ec7ee

7 files changed

Lines changed: 253 additions & 0 deletions

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ export { ErrorBanner } from "./molecules/errors/error-banner";
6868
export { CheckboxFormField } from "./molecules/form-fields/checkbox-form-field";
6969
export { InputFormField } from "./molecules/form-fields/input-form-field";
7070
export { PasswordFormField } from "./molecules/form-fields/password-form-field";
71+
export { SelectFormField } from "./molecules/form-fields/select-form-field";
72+
export { TextAreaFormField } from "./molecules/form-fields/text-area-form-field";
7173

7274
// #endregion Molecules
7375

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { text, boolean } from "@storybook/addon-knobs";
2+
import React from "react";
3+
import { SelectFormField } from "./select-form-field";
4+
import uuid from "uuid";
5+
6+
export default {
7+
component: SelectFormField,
8+
title: "Molecules | Forms / Select Form Field",
9+
};
10+
11+
export const selectFormFieldKnobs = () => (
12+
<SelectFormField
13+
errorMessage={text("Error Message", "")}
14+
label={text("Label", "Tell me something")}
15+
id={uuid.v4()}
16+
onChange={() => {}}
17+
required={boolean("Required", true)}
18+
values={[
19+
{
20+
label: "Option 1",
21+
value: "Value 1",
22+
},
23+
{
24+
label: "Option 2",
25+
value: "Value 2",
26+
},
27+
]}
28+
isValid={boolean("Valid", true)}
29+
/>
30+
);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// import React from "react";
2+
// import { render } from "@testing-library/react";
3+
// import { SelectFormField } from "./select-form-field";
4+
// import faker from "faker";
5+
// import uuid from "uuid";
6+
7+
describe("SelectFormField", () => {
8+
test.skip("TODO - https://github.com/AndcultureCode/AndcultureCode.JavaScript.React.Components/issues/26", () => {});
9+
});
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import React from "react";
2+
import uuid from "uuid";
3+
import { Select, SelectOption } from "../../atoms/forms/select";
4+
5+
// -----------------------------------------------------------------------------------------
6+
// #region Interfaces
7+
// -----------------------------------------------------------------------------------------
8+
9+
export interface SelectFormFieldProps {
10+
errorMessage?: string;
11+
errorMessages?: string[];
12+
fieldId?: string;
13+
id: string;
14+
isValid?: boolean;
15+
name?: string;
16+
label: string;
17+
onChange: (e: SelectOption<any> | undefined) => void;
18+
required?: boolean;
19+
values: SelectOption[];
20+
}
21+
22+
// #endregion Interfaces
23+
24+
// -----------------------------------------------------------------------------------------
25+
// #region Component
26+
// -----------------------------------------------------------------------------------------
27+
28+
const SelectFormField: React.FC<SelectFormFieldProps> = (
29+
props: SelectFormFieldProps
30+
) => {
31+
const {
32+
errorMessage,
33+
errorMessages,
34+
id,
35+
isValid,
36+
name,
37+
label,
38+
onChange,
39+
required,
40+
values,
41+
} = props;
42+
43+
const fieldId = props.fieldId ?? uuid.v4();
44+
45+
return (
46+
<div className={`c-form-field ${isValid ? "" : "-invalid"}`}>
47+
<label htmlFor={fieldId}>
48+
{label}
49+
{required ? "*" : ""}
50+
</label>
51+
<Select options={values} id={id} onChange={onChange} name={name} />
52+
<div className="c-form-field__errors">
53+
{// if
54+
errorMessage != null && errorMessage.length > 0 && (
55+
<label>{errorMessage}</label>
56+
)}
57+
{// if
58+
errorMessages != null &&
59+
errorMessages.map((s: string) => (
60+
<label key={s}>{s}</label>
61+
))}
62+
</div>
63+
</div>
64+
);
65+
};
66+
67+
// #endregion Component
68+
69+
// -----------------------------------------------------------------------------------------
70+
// #region Exports
71+
// -----------------------------------------------------------------------------------------
72+
73+
export { SelectFormField };
74+
75+
// #endregion Exports
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { text, boolean } from "@storybook/addon-knobs";
2+
import React from "react";
3+
import { TextAreaFormField } from "./text-area-form-field";
4+
import faker from "faker";
5+
6+
export default {
7+
component: TextAreaFormField,
8+
title: "Molecules | Forms / TextArea Form Field",
9+
};
10+
11+
export const textAreaFormFieldKnobs = () => (
12+
<TextAreaFormField
13+
disabled={boolean("Disabled", false)}
14+
errorMessage={text("Error Message", "")}
15+
label={text("Label", "Tell me something")}
16+
onChange={() => {}}
17+
placeholder={text("Placeholder", "Placeholder...")}
18+
required={boolean("Required", true)}
19+
value={text("Value", faker.random.words())}
20+
isValid={boolean("Valid", true)}
21+
/>
22+
);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React from "react";
2+
import { render } from "@testing-library/react";
3+
import { TextAreaFormField } from "./text-area-form-field";
4+
import faker from "faker";
5+
6+
describe("TextAreaFormField", () => {
7+
test("when default props, renders input with label", () => {
8+
// Arrange
9+
const expected = faker.random.words();
10+
11+
// Act
12+
const { getByLabelText } = render(
13+
<TextAreaFormField label={expected} onChange={() => {}} />
14+
);
15+
16+
// Assert
17+
expect(getByLabelText(expected)).not.toBeNull();
18+
});
19+
});
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import React from "react";
2+
import uuid from "uuid";
3+
import { TextArea } from "../../atoms/forms/text-area";
4+
5+
// -----------------------------------------------------------------------------------------
6+
// #region Interfaces
7+
// -----------------------------------------------------------------------------------------
8+
9+
export interface TextAreaFormFieldProps {
10+
disabled?: boolean;
11+
errorMessage?: string;
12+
errorMessages?: string[];
13+
fieldId?: string;
14+
/**
15+
* Unique identifier used select the underlying <input> for functional/e2e testing
16+
*/
17+
inputTestId?: string;
18+
isValid?: boolean;
19+
label: string;
20+
maxLength?: number;
21+
name?: string;
22+
onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
23+
placeholder?: string;
24+
required?: boolean;
25+
rows?: number;
26+
value?: string;
27+
}
28+
29+
// #endregion Interfaces
30+
31+
// -----------------------------------------------------------------------------------------
32+
// #region Component
33+
// -----------------------------------------------------------------------------------------
34+
35+
const TextAreaFormField: React.FC<TextAreaFormFieldProps> = (
36+
props: TextAreaFormFieldProps
37+
) => {
38+
const {
39+
disabled,
40+
errorMessage,
41+
errorMessages,
42+
inputTestId,
43+
isValid,
44+
label,
45+
maxLength,
46+
name,
47+
onChange,
48+
placeholder,
49+
required,
50+
rows,
51+
value,
52+
} = props;
53+
54+
const fieldId = props.fieldId ?? uuid.v4();
55+
56+
return (
57+
<div className={`c-form-field ${isValid ? "" : "-invalid"}`}>
58+
<label htmlFor={fieldId}>
59+
{label}
60+
{required ? "*" : ""}
61+
</label>
62+
<TextArea
63+
disabled={disabled}
64+
id={fieldId}
65+
testId={inputTestId}
66+
maxLength={maxLength}
67+
name={name}
68+
onChange={onChange}
69+
placeholder={placeholder}
70+
rows={rows}
71+
value={value}
72+
/>
73+
<div className="c-form-field__errors">
74+
{// if
75+
errorMessage != null && errorMessage.length > 0 && (
76+
<label>{errorMessage}</label>
77+
)}
78+
{// if
79+
errorMessages != null &&
80+
errorMessages.map((s: string) => (
81+
<label key={s}>{s}</label>
82+
))}
83+
</div>
84+
</div>
85+
);
86+
};
87+
88+
// #endregion Component
89+
90+
// -----------------------------------------------------------------------------------------
91+
// #region Exports
92+
// -----------------------------------------------------------------------------------------
93+
94+
export { TextAreaFormField };
95+
96+
// #endregion Exports

0 commit comments

Comments
 (0)