Skip to content

Commit 80ae46b

Browse files
committed
chore(HighContrast): Add form validation
Added validation for name and email only, even though other fields are marked as required. Assisted-by: Cursor (used to generate regexes)
1 parent c4c952c commit 80ae46b

File tree

2 files changed

+101
-7
lines changed

2 files changed

+101
-7
lines changed

packages/react-core/src/demos/HighContrast.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import HelpIcon from '@patternfly/react-icons/dist/esm/icons/help-icon';
2222
import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon';
2323
import QuestionCircleIcon from '@patternfly/react-icons/dist/esm/icons/question-circle-icon';
2424
import BarsIcon from '@patternfly/react-icons/dist/esm/icons/bars-icon';
25+
import ExclamationCircleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon';
2526
import { useState } from 'react';
2627

2728
### High contrast

packages/react-core/src/demos/examples/HighContrast/HighContrast.tsx

Lines changed: 100 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,25 @@ import CogIcon from '@patternfly/react-icons/dist/esm/icons/cog-icon';
5555
import QuestionCircleIcon from '@patternfly/react-icons/dist/esm/icons/question-circle-icon';
5656
import BarsIcon from '@patternfly/react-icons/dist/esm/icons/bars-icon';
5757
import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon';
58+
import ExclamationCircleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon';
5859
import { Ref, RefObject, useState, MouseEvent as ReactMouseEvent, FormEvent } from 'react';
5960
import { DashboardWrapper } from '@patternfly/react-core/dist/js/demos/DashboardWrapper';
6061

62+
type Validate = 'success' | 'warning' | 'error' | 'default';
63+
const emailRegex = /^[^@]+@[^@]+\.[a-zA-Z]+$/i;
64+
const nameRegex = /^[a-zA-ZÀ-ÿ\u0100-\u017F\u0180-\u024F\s\-'.]{2,50}$/i;
65+
6166
export const TabsOpenDemo = () => {
6267
const [activeTabKey, setActiveTabKey] = useState(0);
6368
const [isNavOpen, setIsNavOpen] = useState(true);
6469
const [isDrawerOpen, setIsDrawerOpen] = useState(true);
6570
const [isOpenMap, setIsOpenMap] = useState(new Array(7).fill(false));
71+
const [name, setName] = useState('');
72+
const [validatedName, setValidatedName] = useState<Validate>('default');
73+
const [nameHelperText, setNameHelperText] = useState('Enter your name to continue');
74+
const [email, setEmail] = useState('');
75+
const [validatedEmail, setValidatedEmail] = useState<Validate>('default');
76+
const [emailHelperText, setEmailHelperText] = useState('Enter your email to continue');
6677

6778
const onToggle = (index: number) => () => {
6879
const newState = [...isOpenMap.slice(0, index), !isOpenMap[index], ...isOpenMap.slice(index + 1)];
@@ -103,6 +114,68 @@ export const TabsOpenDemo = () => {
103114

104115
const [isChecked, setIsChecked] = useState(true);
105116

117+
const validateEmail = () => {
118+
if (!emailRegex.test(email)) {
119+
setEmailHelperText('Invalid email address');
120+
setValidatedEmail('error');
121+
return;
122+
}
123+
setEmailHelperText('Valid email address');
124+
setValidatedEmail('success');
125+
};
126+
127+
const validateName = () => {
128+
if (!nameRegex.test(name)) {
129+
setNameHelperText('Invalid name');
130+
setValidatedName('error');
131+
return;
132+
}
133+
setNameHelperText('Valid name');
134+
setValidatedName('success');
135+
};
136+
137+
const handleEmailChange = (_event, newEmail: string) => {
138+
setEmail(newEmail);
139+
};
140+
141+
const handleNameChange = (_event, newName: string) => {
142+
setName(newName);
143+
};
144+
145+
const resetForm = () => {
146+
setName('');
147+
setEmail('');
148+
setValidatedName('default');
149+
setValidatedEmail('default');
150+
setNameHelperText('Enter your name to continue');
151+
setEmailHelperText('Enter your email to continue');
152+
};
153+
154+
const handleSubmit = (_event) => {
155+
if (emailRegex.test(email) && nameRegex.test(name)) {
156+
resetForm();
157+
} else {
158+
validateEmail();
159+
validateName();
160+
}
161+
};
162+
163+
const handleCancel = () => {
164+
resetForm();
165+
};
166+
167+
const generateAlertContent = () => {
168+
if (validatedEmail === 'error' && validatedName === 'error') {
169+
return 'Please provide a valid name and email address';
170+
}
171+
if (validatedEmail === 'error') {
172+
return 'Please provide a valid email address';
173+
}
174+
if (validatedName === 'error') {
175+
return 'Please provide a valid name';
176+
}
177+
};
178+
106179
const pageForm = (
107180
<Form>
108181
<FormGroup label="Name" isRequired fieldId="horizontal-form-name">
@@ -112,11 +185,18 @@ export const TabsOpenDemo = () => {
112185
id="horizontal-form-name"
113186
aria-describedby="horizontal-form-name-helper"
114187
name="horizontal-form-name"
115-
value="John Doe"
188+
value={name}
189+
onChange={handleNameChange}
190+
validated={validatedName}
116191
/>
117192
<FormHelperText>
118193
<HelperText>
119-
<HelperTextItem variant="success">Valid name</HelperTextItem>
194+
<HelperTextItem
195+
variant={validatedName}
196+
{...(validatedName === 'error' && { icon: <ExclamationCircleIcon /> })}
197+
>
198+
{nameHelperText}
199+
</HelperTextItem>
120200
</HelperText>
121201
</FormHelperText>
122202
</FormGroup>
@@ -126,11 +206,18 @@ export const TabsOpenDemo = () => {
126206
type="text"
127207
id="horizontal-form-email"
128208
name="horizontal-form-email"
129-
value="John_doe@gmail"
209+
value={email}
210+
onChange={handleEmailChange}
211+
validated={validatedEmail}
130212
/>
131213
<FormHelperText>
132214
<HelperText>
133-
<HelperTextItem variant="error">Invalid email</HelperTextItem>
215+
<HelperTextItem
216+
variant={validatedEmail}
217+
{...(validatedEmail === 'error' && { icon: <ExclamationCircleIcon /> })}
218+
>
219+
{emailHelperText}
220+
</HelperTextItem>
134221
</HelperText>
135222
</FormHelperText>
136223
</FormGroup>
@@ -161,8 +248,12 @@ export const TabsOpenDemo = () => {
161248
<TextArea autoResize />
162249
</FormGroup>
163250
<ActionGroup>
164-
<Button variant="primary">Submit</Button>
165-
<Button variant="link">Cancel</Button>
251+
<Button variant="primary" onClick={handleSubmit}>
252+
Submit
253+
</Button>
254+
<Button variant="link" onClick={handleCancel}>
255+
Cancel
256+
</Button>
166257
</ActionGroup>
167258
</Form>
168259
);
@@ -589,7 +680,9 @@ export const TabsOpenDemo = () => {
589680
<PageSection isWidthLimited padding={{ default: 'noPadding' }}>
590681
<TabContent key={0} eventKey={0} id={`tabContent${0}`} activeKey={activeTabKey} hidden={0 !== activeTabKey}>
591682
<PageSection>
592-
<Alert isInline variant="danger" title="Danger alert title" ouiaId="DangerAlert" />
683+
{(validatedEmail === 'error' || validatedName === 'error') && (
684+
<Alert isInline variant="danger" title={generateAlertContent()} ouiaId="DangerAlert" />
685+
)}
593686
</PageSection>
594687
<PageSection>{pageForm}</PageSection>
595688
</TabContent>

0 commit comments

Comments
 (0)