@patternfly/react-core 4.223.2 → 4.223.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/esm/components/Form/FormGroup.d.ts +4 -2
- package/dist/esm/components/Form/FormGroup.d.ts.map +1 -1
- package/dist/esm/components/Form/FormGroup.js +4 -3
- package/dist/esm/components/Form/FormGroup.js.map +1 -1
- package/dist/js/components/Form/FormGroup.d.ts +4 -2
- package/dist/js/components/Form/FormGroup.d.ts.map +1 -1
- package/dist/js/components/Form/FormGroup.js +4 -3
- package/dist/js/components/Form/FormGroup.js.map +1 -1
- package/dist/umd/react-core.js +3 -3
- package/dist/umd/react-core.min.js +1 -1
- package/package.json +6 -6
- package/src/components/Form/FormGroup.tsx +40 -29
- package/src/components/Form/examples/Form.md +12 -1271
- package/src/components/Form/examples/FormBasic.tsx +122 -0
- package/src/components/Form/examples/FormFieldGroups.tsx +324 -0
- package/src/components/Form/examples/FormGrid.tsx +66 -0
- package/src/components/Form/examples/FormGroupLabelInfo.tsx +72 -0
- package/src/components/Form/examples/FormHorizontal.tsx +118 -0
- package/src/components/Form/examples/FormHorizontalHelper.tsx +23 -0
- package/src/components/Form/examples/FormHorizontalStacked.tsx +11 -0
- package/src/components/Form/examples/FormInvalid.tsx +47 -0
- package/src/components/Form/examples/FormInvalidWithFormAlert.tsx +52 -0
- package/src/components/Form/examples/FormLimitWidth.tsx +122 -0
- package/src/components/Form/examples/FormSections.tsx +44 -0
- package/src/components/Form/examples/FormValidated.tsx +60 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Form,
|
|
4
|
+
FormGroup,
|
|
5
|
+
TextInput,
|
|
6
|
+
TextArea,
|
|
7
|
+
FormSelect,
|
|
8
|
+
FormSelectOption,
|
|
9
|
+
Checkbox,
|
|
10
|
+
ActionGroup,
|
|
11
|
+
Button,
|
|
12
|
+
Radio
|
|
13
|
+
} from '@patternfly/react-core';
|
|
14
|
+
|
|
15
|
+
export const FormHorizontal: React.FunctionComponent = () => {
|
|
16
|
+
const [name, setName] = React.useState('');
|
|
17
|
+
const [email, setEmail] = React.useState('');
|
|
18
|
+
const [experience, setExperience] = React.useState('');
|
|
19
|
+
const [option, setOption] = React.useState('please choose');
|
|
20
|
+
|
|
21
|
+
const handleNameChange = (name: string) => {
|
|
22
|
+
setName(name);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const handleEmailChange = (email: string) => {
|
|
26
|
+
setEmail(email);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const handleExperienceChange = (experience: string) => {
|
|
30
|
+
setExperience(experience);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const handleOptionChange = (value: string, _event: React.FormEvent<HTMLSelectElement>) => {
|
|
34
|
+
setOption(value);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const options = [
|
|
38
|
+
{ value: 'select one', label: 'Select one', disabled: false },
|
|
39
|
+
{ value: 'mr', label: 'Mr', disabled: false },
|
|
40
|
+
{ value: 'miss', label: 'Miss', disabled: false },
|
|
41
|
+
{ value: 'mrs', label: 'Mrs', disabled: false },
|
|
42
|
+
{ value: 'ms', label: 'Ms', disabled: false },
|
|
43
|
+
{ value: 'dr', label: 'Dr', disabled: false },
|
|
44
|
+
{ value: 'other', label: 'Other', disabled: false }
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<Form isHorizontal>
|
|
49
|
+
<FormGroup
|
|
50
|
+
label="Full name"
|
|
51
|
+
isRequired
|
|
52
|
+
fieldId="horizontal-form-name"
|
|
53
|
+
helperText="Include your middle name if you have one."
|
|
54
|
+
>
|
|
55
|
+
<TextInput
|
|
56
|
+
value={name}
|
|
57
|
+
isRequired
|
|
58
|
+
type="text"
|
|
59
|
+
id="horizontal-form-name"
|
|
60
|
+
aria-describedby="horizontal-form-name-helper"
|
|
61
|
+
name="horizontal-form-name"
|
|
62
|
+
onChange={handleNameChange}
|
|
63
|
+
/>
|
|
64
|
+
</FormGroup>
|
|
65
|
+
<FormGroup label="Email" isRequired fieldId="horizontal-form-email">
|
|
66
|
+
<TextInput
|
|
67
|
+
value={email}
|
|
68
|
+
isRequired
|
|
69
|
+
type="email"
|
|
70
|
+
id="horizontal-form-email"
|
|
71
|
+
name="horizontal-form-email"
|
|
72
|
+
onChange={handleEmailChange}
|
|
73
|
+
/>
|
|
74
|
+
</FormGroup>
|
|
75
|
+
<FormGroup label="Your title" fieldId="horizontal-form-title">
|
|
76
|
+
<FormSelect
|
|
77
|
+
value={option}
|
|
78
|
+
onChange={handleOptionChange}
|
|
79
|
+
id="horizontal-form-title"
|
|
80
|
+
name="horizontal-form-title"
|
|
81
|
+
aria-label="Your title"
|
|
82
|
+
>
|
|
83
|
+
{options.map((option, index) => (
|
|
84
|
+
<FormSelectOption isDisabled={option.disabled} key={index} value={option.value} label={option.label} />
|
|
85
|
+
))}
|
|
86
|
+
</FormSelect>
|
|
87
|
+
</FormGroup>
|
|
88
|
+
<FormGroup label="Your experience" fieldId="horizontal-form-exp">
|
|
89
|
+
<TextArea
|
|
90
|
+
value={experience}
|
|
91
|
+
onChange={handleExperienceChange}
|
|
92
|
+
id="horizontal-form-exp"
|
|
93
|
+
name="horizontal-form-exp"
|
|
94
|
+
/>
|
|
95
|
+
</FormGroup>
|
|
96
|
+
<FormGroup
|
|
97
|
+
label="How can we contact you?"
|
|
98
|
+
isStack
|
|
99
|
+
fieldId="horizontal-form-checkbox-group"
|
|
100
|
+
hasNoPaddingTop
|
|
101
|
+
role="group"
|
|
102
|
+
>
|
|
103
|
+
<Checkbox label="Email" id="alt-form-checkbox-1" name="alt-form-checkbox-1" />
|
|
104
|
+
<Checkbox label="Phone" id="alt-form-checkbox-2" name="alt-form-checkbox-2" />
|
|
105
|
+
<Checkbox label="Mail" id="alt-form-checkbox-3" name="alt-form-checkbox-3" />
|
|
106
|
+
</FormGroup>
|
|
107
|
+
<FormGroup role="radiogroup" isStack fieldId="horizontal-form-radio-group" hasNoPaddingTop label="Time zone">
|
|
108
|
+
<Radio name="horizontal-inline-radio" label="Eastern" id="horizontal-inline-radio-01" />
|
|
109
|
+
<Radio name="horizontal-inline-radio" label="Central" id="horizontal-inline-radio-02" />
|
|
110
|
+
<Radio name="horizontal-inline-radio" label="Pacific" id="horizontal-inline-radio-03" />
|
|
111
|
+
</FormGroup>
|
|
112
|
+
<ActionGroup>
|
|
113
|
+
<Button variant="primary">Submit</Button>
|
|
114
|
+
<Button variant="link">Cancel</Button>
|
|
115
|
+
</ActionGroup>
|
|
116
|
+
</Form>
|
|
117
|
+
);
|
|
118
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Form, FormGroup, Checkbox } from '@patternfly/react-core';
|
|
3
|
+
|
|
4
|
+
export const FormHorizontalFormHelperText: React.FunctionComponent = () => {
|
|
5
|
+
const [helperText] = React.useState('Select all that apply:');
|
|
6
|
+
|
|
7
|
+
return (
|
|
8
|
+
<Form isHorizontal>
|
|
9
|
+
<FormGroup
|
|
10
|
+
label="Label"
|
|
11
|
+
helperText={helperText}
|
|
12
|
+
isHelperTextBeforeField
|
|
13
|
+
hasNoPaddingTop
|
|
14
|
+
isStack
|
|
15
|
+
fieldId="horizontal-form-helper-options"
|
|
16
|
+
role="group"
|
|
17
|
+
>
|
|
18
|
+
<Checkbox label="Option 1" id="option-03" />
|
|
19
|
+
<Checkbox label="Option 2" id="option-04" />
|
|
20
|
+
</FormGroup>
|
|
21
|
+
</Form>
|
|
22
|
+
);
|
|
23
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Form, FormGroup, Checkbox } from '@patternfly/react-core';
|
|
3
|
+
|
|
4
|
+
export const FormHorizontalStacked: React.FunctionComponent = () => (
|
|
5
|
+
<Form isHorizontal>
|
|
6
|
+
<FormGroup role="group" label="Label" hasNoPaddingTop fieldId="horizontal-form-stacked-options" isStack>
|
|
7
|
+
<Checkbox label="option 1" id="option-01" />
|
|
8
|
+
<Checkbox label="option 2" id="option-02" />
|
|
9
|
+
</FormGroup>
|
|
10
|
+
</Form>
|
|
11
|
+
);
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Form, FormGroup, TextInput, FormHelperText } from '@patternfly/react-core';
|
|
3
|
+
import ExclamationCircleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon';
|
|
4
|
+
|
|
5
|
+
export const FormInvalid: React.FunctionComponent = () => {
|
|
6
|
+
type validate = 'success' | 'warning' | 'error' | 'default';
|
|
7
|
+
|
|
8
|
+
const [age, setAge] = React.useState('Five');
|
|
9
|
+
const [validated, setValidated] = React.useState<validate>('error');
|
|
10
|
+
|
|
11
|
+
const handleAgeChange = (age: string, _event: React.FormEvent<HTMLInputElement>) => {
|
|
12
|
+
setAge(age);
|
|
13
|
+
if (age === '') {
|
|
14
|
+
setValidated('default');
|
|
15
|
+
} else if (/^\d+$/.test(age)) {
|
|
16
|
+
setValidated('success');
|
|
17
|
+
} else {
|
|
18
|
+
setValidated('error');
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<Form>
|
|
24
|
+
<FormGroup
|
|
25
|
+
label="Age"
|
|
26
|
+
type="number"
|
|
27
|
+
helperText={
|
|
28
|
+
<FormHelperText icon={<ExclamationCircleIcon />} isHidden={validated !== 'default'}>
|
|
29
|
+
Please enter your age
|
|
30
|
+
</FormHelperText>
|
|
31
|
+
}
|
|
32
|
+
helperTextInvalid="Must be a number"
|
|
33
|
+
helperTextInvalidIcon={<ExclamationCircleIcon />}
|
|
34
|
+
fieldId="age-1"
|
|
35
|
+
validated={validated}
|
|
36
|
+
>
|
|
37
|
+
<TextInput
|
|
38
|
+
validated={validated}
|
|
39
|
+
value={age}
|
|
40
|
+
id="age-1"
|
|
41
|
+
aria-describedby="age-1-helper"
|
|
42
|
+
onChange={handleAgeChange}
|
|
43
|
+
/>
|
|
44
|
+
</FormGroup>
|
|
45
|
+
</Form>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Alert, Form, FormAlert, FormGroup, TextInput, FormHelperText } from '@patternfly/react-core';
|
|
3
|
+
import ExclamationCircleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon';
|
|
4
|
+
|
|
5
|
+
export const FormInvalidWithAlert: React.FunctionComponent = () => {
|
|
6
|
+
type validate = 'success' | 'warning' | 'error' | 'default';
|
|
7
|
+
|
|
8
|
+
const [age, setAge] = React.useState('Five');
|
|
9
|
+
const [validated, setValidated] = React.useState<validate>('error');
|
|
10
|
+
|
|
11
|
+
const handleAgeChange = (age: string, _event: React.FormEvent<HTMLInputElement>) => {
|
|
12
|
+
setAge(age);
|
|
13
|
+
if (age === '') {
|
|
14
|
+
setValidated('default');
|
|
15
|
+
} else if (/^\d+$/.test(age)) {
|
|
16
|
+
setValidated('success');
|
|
17
|
+
} else {
|
|
18
|
+
setValidated('error');
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<Form>
|
|
24
|
+
{validated === 'error' && (
|
|
25
|
+
<FormAlert>
|
|
26
|
+
<Alert variant="danger" title="Fill out all required fields before continuing." aria-live="polite" isInline />
|
|
27
|
+
</FormAlert>
|
|
28
|
+
)}
|
|
29
|
+
<FormGroup
|
|
30
|
+
label="Age"
|
|
31
|
+
type="number"
|
|
32
|
+
helperText={
|
|
33
|
+
<FormHelperText icon={<ExclamationCircleIcon />} isHidden={validated !== 'default'}>
|
|
34
|
+
Please enter your age
|
|
35
|
+
</FormHelperText>
|
|
36
|
+
}
|
|
37
|
+
helperTextInvalid="Must be a number"
|
|
38
|
+
helperTextInvalidIcon={<ExclamationCircleIcon />}
|
|
39
|
+
fieldId="age-2"
|
|
40
|
+
validated={validated}
|
|
41
|
+
>
|
|
42
|
+
<TextInput
|
|
43
|
+
validated={validated}
|
|
44
|
+
value={age}
|
|
45
|
+
id="age-2"
|
|
46
|
+
aria-describedby="age-2-helper"
|
|
47
|
+
onChange={handleAgeChange}
|
|
48
|
+
/>
|
|
49
|
+
</FormGroup>
|
|
50
|
+
</Form>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Form, FormGroup, TextInput, Checkbox, Popover, ActionGroup, Button, Radio } from '@patternfly/react-core';
|
|
3
|
+
import HelpIcon from '@patternfly/react-icons/dist/esm/icons/help-icon';
|
|
4
|
+
|
|
5
|
+
export const FormLimitWidth: React.FunctionComponent = () => {
|
|
6
|
+
const [name, setName] = React.useState('');
|
|
7
|
+
const [email, setEmail] = React.useState('');
|
|
8
|
+
const [phone, setPhone] = React.useState('');
|
|
9
|
+
|
|
10
|
+
const handleNameChange = (name: string) => {
|
|
11
|
+
setName(name);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const handleEmailChange = (email: string) => {
|
|
15
|
+
setEmail(email);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const handlePhoneChange = (phone: string) => {
|
|
19
|
+
setPhone(phone);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<Form isWidthLimited>
|
|
24
|
+
<FormGroup
|
|
25
|
+
label="Full name"
|
|
26
|
+
labelIcon={
|
|
27
|
+
<Popover
|
|
28
|
+
headerContent={
|
|
29
|
+
<div>
|
|
30
|
+
The{' '}
|
|
31
|
+
<a href="https://schema.org/name" target="_blank" rel="noreferrer">
|
|
32
|
+
name
|
|
33
|
+
</a>{' '}
|
|
34
|
+
of a{' '}
|
|
35
|
+
<a href="https://schema.org/Person" target="_blank" rel="noreferrer">
|
|
36
|
+
Person
|
|
37
|
+
</a>
|
|
38
|
+
</div>
|
|
39
|
+
}
|
|
40
|
+
bodyContent={
|
|
41
|
+
<div>
|
|
42
|
+
Often composed of{' '}
|
|
43
|
+
<a href="https://schema.org/givenName" target="_blank" rel="noreferrer">
|
|
44
|
+
givenName
|
|
45
|
+
</a>{' '}
|
|
46
|
+
and{' '}
|
|
47
|
+
<a href="https://schema.org/familyName" target="_blank" rel="noreferrer">
|
|
48
|
+
familyName
|
|
49
|
+
</a>
|
|
50
|
+
.
|
|
51
|
+
</div>
|
|
52
|
+
}
|
|
53
|
+
>
|
|
54
|
+
<button
|
|
55
|
+
type="button"
|
|
56
|
+
aria-label="More info for name field"
|
|
57
|
+
onClick={e => e.preventDefault()}
|
|
58
|
+
aria-describedby="simple-form-name-02"
|
|
59
|
+
className="pf-c-form__group-label-help"
|
|
60
|
+
>
|
|
61
|
+
<HelpIcon noVerticalAlign />
|
|
62
|
+
</button>
|
|
63
|
+
</Popover>
|
|
64
|
+
}
|
|
65
|
+
isRequired
|
|
66
|
+
fieldId="simple-form-name-02"
|
|
67
|
+
helperText="Include your middle name if you have one."
|
|
68
|
+
>
|
|
69
|
+
<TextInput
|
|
70
|
+
isRequired
|
|
71
|
+
type="text"
|
|
72
|
+
id="simple-form-name-02"
|
|
73
|
+
name="simple-form-name-02"
|
|
74
|
+
aria-describedby="simple-form-name-02-helper"
|
|
75
|
+
value={name}
|
|
76
|
+
onChange={handleNameChange}
|
|
77
|
+
/>
|
|
78
|
+
</FormGroup>
|
|
79
|
+
<FormGroup label="Email" isRequired fieldId="simple-form-email-02">
|
|
80
|
+
<TextInput
|
|
81
|
+
isRequired
|
|
82
|
+
type="email"
|
|
83
|
+
id="simple-form-email-02"
|
|
84
|
+
name="simple-form-email-02"
|
|
85
|
+
value={email}
|
|
86
|
+
onChange={handleEmailChange}
|
|
87
|
+
/>
|
|
88
|
+
</FormGroup>
|
|
89
|
+
<FormGroup label="Phone number" isRequired fieldId="simple-form-number">
|
|
90
|
+
<TextInput
|
|
91
|
+
isRequired
|
|
92
|
+
type="tel"
|
|
93
|
+
placeholder="555-555-5555"
|
|
94
|
+
id="simple-form-number"
|
|
95
|
+
name="simple-form-number"
|
|
96
|
+
value={phone}
|
|
97
|
+
onChange={handlePhoneChange}
|
|
98
|
+
/>
|
|
99
|
+
</FormGroup>
|
|
100
|
+
<FormGroup role="group" isInline fieldId="limit-width-form-checkbox-group" label="How can we contact you?">
|
|
101
|
+
<Checkbox label="Email" aria-label="Email" id="inlinecheck04" />
|
|
102
|
+
<Checkbox label="Phone" aria-label="Phone" id="inlinecheck05" />
|
|
103
|
+
<Checkbox label="Mail" aria-label="Mail" id="inlinecheck06" />
|
|
104
|
+
</FormGroup>
|
|
105
|
+
<FormGroup role="radiogroup" isInline fieldId="limit-width-form-radio-group" label="Time zone">
|
|
106
|
+
<Radio name="limit-width-radio" label="Eastern" id="limit-width-inline-radio-01" />
|
|
107
|
+
<Radio name="limit-width-radio" label="Central" id="limit-width-inline-radio-02" />
|
|
108
|
+
<Radio name="limit-width-radio" label="Pacific" id="limit-width-inline-radio-03" />
|
|
109
|
+
</FormGroup>
|
|
110
|
+
<FormGroup label="Additional note" fieldId="simple-form-note-02">
|
|
111
|
+
<TextInput isDisabled type="text" id="simple-form-note-02" name="simple-form-number" value="disabled" />
|
|
112
|
+
</FormGroup>
|
|
113
|
+
<FormGroup fieldId="checkbox02">
|
|
114
|
+
<Checkbox label="I'd like updates via email." id="checkbox02" name="checkbox02" aria-label="Update via email" />
|
|
115
|
+
</FormGroup>
|
|
116
|
+
<ActionGroup>
|
|
117
|
+
<Button variant="primary">Submit</Button>
|
|
118
|
+
<Button variant="link">Cancel</Button>
|
|
119
|
+
</ActionGroup>
|
|
120
|
+
</Form>
|
|
121
|
+
);
|
|
122
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Form, FormGroup, FormSection, TextInput } from '@patternfly/react-core';
|
|
3
|
+
|
|
4
|
+
export const FormSections: React.FunctionComponent = () => {
|
|
5
|
+
const [input1, setInput1] = React.useState('');
|
|
6
|
+
const [input2, setInput2] = React.useState('');
|
|
7
|
+
|
|
8
|
+
const handleInputChange1 = (input1: string, _event: React.FormEvent<HTMLInputElement>) => {
|
|
9
|
+
setInput1(input1);
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const handleInputChange2 = (input2: string, _event: React.FormEvent<HTMLInputElement>) => {
|
|
13
|
+
setInput2(input2);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<Form>
|
|
18
|
+
<FormSection>
|
|
19
|
+
<FormGroup label="Form section 1 input" isRequired fieldId="simple-form-section-1-input">
|
|
20
|
+
<TextInput
|
|
21
|
+
isRequired
|
|
22
|
+
type="text"
|
|
23
|
+
id="simple-form-section-1-input"
|
|
24
|
+
name="simple-form-section-1-input"
|
|
25
|
+
value={input1}
|
|
26
|
+
onChange={handleInputChange1}
|
|
27
|
+
/>
|
|
28
|
+
</FormGroup>
|
|
29
|
+
</FormSection>
|
|
30
|
+
<FormSection title="Form section 2 (optional title)" titleElement="h2">
|
|
31
|
+
<FormGroup label="Form section 2 input" isRequired fieldId="simple-form-section-2-input">
|
|
32
|
+
<TextInput
|
|
33
|
+
isRequired
|
|
34
|
+
type="text"
|
|
35
|
+
id="simple-form-section-2-input"
|
|
36
|
+
name="simple-form-section-2-input"
|
|
37
|
+
value={input2}
|
|
38
|
+
onChange={handleInputChange2}
|
|
39
|
+
/>
|
|
40
|
+
</FormGroup>
|
|
41
|
+
</FormSection>
|
|
42
|
+
</Form>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Form, FormGroup, TextInput } from '@patternfly/react-core';
|
|
3
|
+
import ExclamationCircleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon';
|
|
4
|
+
|
|
5
|
+
export const FormValidated: React.FunctionComponent = () => {
|
|
6
|
+
type validate = 'success' | 'warning' | 'error' | 'default';
|
|
7
|
+
|
|
8
|
+
const [age, setAge] = React.useState('Five');
|
|
9
|
+
const [invalidText, setInvalidText] = React.useState('Must be a number');
|
|
10
|
+
const [validated, setValidated] = React.useState<validate>('default');
|
|
11
|
+
const [helperText, setHelperText] = React.useState('Enter your age to continue');
|
|
12
|
+
|
|
13
|
+
const handleAgeChange = (age: string, _event: React.FormEvent<HTMLInputElement>) => {
|
|
14
|
+
setAge(age);
|
|
15
|
+
setValidated('default');
|
|
16
|
+
setHelperText('Validating...');
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// useEffect is used to simulate a server call to validate the age 2000ms after the user has entered a value, preventing calling the server on every keystroke
|
|
20
|
+
React.useEffect(() => {
|
|
21
|
+
const timer = setTimeout(() => {
|
|
22
|
+
if (/^\d+$/.test(age)) {
|
|
23
|
+
if (parseInt(age) >= 21) {
|
|
24
|
+
setValidated('success');
|
|
25
|
+
setHelperText('Enjoy your stay');
|
|
26
|
+
} else {
|
|
27
|
+
setValidated('warning');
|
|
28
|
+
setHelperText('You must be at least 21 years old to continue');
|
|
29
|
+
}
|
|
30
|
+
} else {
|
|
31
|
+
setValidated('error');
|
|
32
|
+
setInvalidText('Must be a number');
|
|
33
|
+
}
|
|
34
|
+
}, 2000);
|
|
35
|
+
|
|
36
|
+
return () => clearTimeout(timer);
|
|
37
|
+
}, [age]);
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<Form>
|
|
41
|
+
<FormGroup
|
|
42
|
+
label="Age"
|
|
43
|
+
type="number"
|
|
44
|
+
helperText={helperText}
|
|
45
|
+
helperTextInvalid={invalidText}
|
|
46
|
+
helperTextInvalidIcon={<ExclamationCircleIcon />}
|
|
47
|
+
fieldId="age-3"
|
|
48
|
+
validated={validated}
|
|
49
|
+
>
|
|
50
|
+
<TextInput
|
|
51
|
+
validated={validated}
|
|
52
|
+
value={age}
|
|
53
|
+
id="age-3"
|
|
54
|
+
aria-describedby="age-3-helper"
|
|
55
|
+
onChange={handleAgeChange}
|
|
56
|
+
/>
|
|
57
|
+
</FormGroup>
|
|
58
|
+
</Form>
|
|
59
|
+
);
|
|
60
|
+
};
|