Skip to content

Commit ec3487a

Browse files
committed
fix: added delayed validation to TimeZone and fixed race condition
1 parent 8c3d43b commit ec3487a

2 files changed

Lines changed: 53 additions & 63 deletions

File tree

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ To see how components like alerts, navigation, and forms can now use motion to p
3636
Currently, this demo includes animations for:
3737

3838
* Alerts.
39+
* Tabs.
3940
* The notification badge and notification drawer.
4041
* The hamburger/navigation menu icon.
4142
* The masthead settings icon.

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

Lines changed: 52 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,4 @@
1-
import {
2-
Fragment,
3-
useRef,
4-
useState,
5-
useEffect,
6-
ReactNode,
7-
FunctionComponent,
8-
FormEvent,
9-
RefObject,
10-
MouseEvent,
11-
TransitionEvent
12-
} from 'react';
1+
import { Fragment, useRef, useState, useEffect, ReactNode, FunctionComponent, FormEvent, RefObject } from 'react';
132
import {
143
AlertGroup,
154
Alert,
@@ -44,6 +33,8 @@ import {
4433
FormHelperText,
4534
FormAlert,
4635
FormGroupLabelHelp,
36+
FormSelect,
37+
FormSelectOption,
4738
HelperText,
4839
HelperTextItem,
4940
Icon,
@@ -1320,7 +1311,6 @@ export const Animations: FunctionComponent = () => {
13201311
const [name, setName] = useState('');
13211312
const [email, setEmail] = useState('');
13221313
const [version, setVersion] = useState('');
1323-
const [isTimeZoneOpen, setIsTimeZoneOpen] = useState(false);
13241314
const [selectedTimeZone, setSelectedTimeZone] = useState('');
13251315
const [password, setPassword] = useState('');
13261316
const [isSuccess, setIsSuccess] = useState(false);
@@ -1337,6 +1327,9 @@ export const Animations: FunctionComponent = () => {
13371327
const [isNameValidating, setIsNameValidating] = useState(false);
13381328
const [isPasswordValidating, setIsPasswordValidating] = useState(false);
13391329

1330+
const [timeZoneValidated, setTimeZoneValidated] = useState('default');
1331+
const [timeZoneHelperText, setTimeZoneHelperText] = useState('A time zone is required for scheduling tasks.');
1332+
13401333
// useEffect for delayed name validation
13411334
useEffect(() => {
13421335
if (name === '') {
@@ -1379,10 +1372,24 @@ export const Animations: FunctionComponent = () => {
13791372
};
13801373
}, [password]);
13811374

1375+
useEffect(() => {
1376+
if (selectedTimeZone === '') {
1377+
setTimeZoneValidated('default');
1378+
setTimeZoneHelperText('A time zone is required for scheduling tasks.');
1379+
return;
1380+
}
1381+
1382+
const timerId = setTimeout(() => {
1383+
setTimeZoneValidated('success');
1384+
setTimeZoneHelperText('Time zone successfully selected.');
1385+
}, 2000);
1386+
1387+
return () => clearTimeout(timerId);
1388+
}, [selectedTimeZone]);
1389+
13821390
const handleNameChange = (_event: React.FormEvent<HTMLInputElement>, name: string) => {
13831391
setName(name);
13841392
setIsNameValid('default');
1385-
setIsNameValidating(false);
13861393
};
13871394

13881395
const handleEmailChange = (_event: React.FormEvent<HTMLInputElement>, email: string) => {
@@ -1396,31 +1403,21 @@ export const Animations: FunctionComponent = () => {
13961403
const handlePasswordChange = (_event: React.FormEvent<HTMLInputElement>, password: string) => {
13971404
setPassword(password);
13981405
setIsPasswordValid('default');
1399-
setIsPasswordValidating(false);
14001406
};
14011407

1402-
const onTimeZoneSelect = (
1403-
_event: React.MouseEvent | React.ChangeEvent | undefined,
1404-
selection: string | number | undefined
1405-
) => {
1406-
setSelectedTimeZone(selection as string);
1407-
setIsTimeZoneOpen(false);
1408+
const handleTimeZoneChange = (event: React.FormEvent<HTMLSelectElement>, value: string) => {
1409+
setSelectedTimeZone(value);
1410+
setTimeZoneValidated('default');
1411+
setTimeZoneHelperText('Validating...');
14081412
};
14091413

1410-
const timeZoneToggle = (toggleRef: React.Ref<MenuToggleElement>) => (
1411-
<MenuToggle ref={toggleRef} onClick={() => setIsTimeZoneOpen(!isTimeZoneOpen)} isExpanded={isTimeZoneOpen}>
1412-
{selectedTimeZone || 'Select time zone'}
1413-
</MenuToggle>
1414-
);
1415-
14161414
const handleSubmit = () => {
14171415
setActionCompleted(true);
14181416
if (
14191417
isPasswordValid === 'success' &&
14201418
isNameValid === 'success' &&
1421-
selectedTimeZone.length > 0 &&
1422-
email.includes('@') &&
1423-
version.length > 0
1419+
timeZoneValidated === 'success' &&
1420+
email.includes('@')
14241421
) {
14251422
setIsSuccess(true);
14261423
setTimeout(() => {
@@ -1441,7 +1438,7 @@ export const Animations: FunctionComponent = () => {
14411438
{actionCompleted &&
14421439
(isSuccess ? (
14431440
<FormAlert>
1444-
<AlertGroup hasAnimations>
1441+
<AlertGroup>
14451442
<Alert
14461443
variant="success"
14471444
title="Successfully created database"
@@ -1453,7 +1450,7 @@ export const Animations: FunctionComponent = () => {
14531450
</FormAlert>
14541451
) : (
14551452
<FormAlert>
1456-
<AlertGroup hasAnimations>
1453+
<AlertGroup>
14571454
<Alert
14581455
variant="danger"
14591456
title="Failed to create database. Please ensure all fields are filled out correctly."
@@ -1497,18 +1494,16 @@ export const Animations: FunctionComponent = () => {
14971494
/>
14981495
<FormHelperText>
14991496
<HelperText>
1500-
<HelperTextItem
1501-
icon={isNameValid === 'error' ? <ExclamationCircleIcon /> : undefined}
1502-
variant={isNameValid as validationStatus}
1503-
>
1497+
<HelperTextItem variant={isNameValid as validationStatus}>
15041498
{(() => {
15051499
if (isNameValidating) {
15061500
return 'Validating...';
15071501
}
15081502
if (isNameValid === 'error') {
15091503
return 'Must contain only lowercase letters, numbers, and hyphens.';
1504+
} else {
1505+
return 'Must be a unique name.';
15101506
}
1511-
return 'Must be a unique name.';
15121507
})()}
15131508
</HelperTextItem>
15141509
</HelperText>
@@ -1523,39 +1518,38 @@ export const Animations: FunctionComponent = () => {
15231518
value={email}
15241519
onChange={handleEmailChange}
15251520
/>
1521+
<HelperText>
1522+
<HelperTextItem>Must be a valid email address containing an @ symbol.</HelperTextItem>
1523+
</HelperText>
15261524
</FormGroup>
15271525
<FormGroup label="Database version" fieldId="simple-form-version-01">
15281526
<TextInput
15291527
type="text"
15301528
id="simple-form-version-01"
15311529
name="simple-form-version-01"
1532-
placeholder="12c"
1530+
placeholder="e.g. 12c"
15331531
value={version}
15341532
onChange={handleVersionChange}
15351533
/>
15361534
</FormGroup>
15371535
<FormGroup isRequired label="Time zone" fieldId="timezone-select">
1538-
<Select
1536+
<FormSelect
15391537
id="timezone-select"
1538+
value={selectedTimeZone}
1539+
onChange={handleTimeZoneChange}
15401540
aria-label="Select time zone"
1541-
isOpen={isTimeZoneOpen}
1542-
selected={selectedTimeZone}
1543-
onSelect={onTimeZoneSelect}
1544-
onOpenChange={setIsTimeZoneOpen}
1545-
toggle={timeZoneToggle}
1541+
validated={timeZoneValidated as validationStatus}
15461542
>
1547-
<SelectList>
1548-
<SelectOption value="Eastern" key="eastern">
1549-
Eastern
1550-
</SelectOption>
1551-
<SelectOption value="Central" key="central">
1552-
Central
1553-
</SelectOption>
1554-
<SelectOption value="Pacific" key="pacific">
1555-
Pacific
1556-
</SelectOption>
1557-
</SelectList>
1558-
</Select>
1543+
<FormSelectOption isPlaceholder value="" label="Select a time zone" />
1544+
<FormSelectOption value="Eastern" label="Eastern" />
1545+
<FormSelectOption value="Central" label="Central" />
1546+
<FormSelectOption value="Pacific" label="Pacific" />
1547+
</FormSelect>
1548+
<FormHelperText>
1549+
<HelperText>
1550+
<HelperTextItem variant={timeZoneValidated as validationStatus}>{timeZoneHelperText}</HelperTextItem>
1551+
</HelperText>
1552+
</FormHelperText>
15591553
</FormGroup>
15601554
<FormGroup label="Admin password" isRequired fieldId="simple-form-password-01">
15611555
<TextInput
@@ -1570,10 +1564,7 @@ export const Animations: FunctionComponent = () => {
15701564
/>
15711565
<FormHelperText>
15721566
<HelperText>
1573-
<HelperTextItem
1574-
icon={isPasswordValid === 'error' ? <ExclamationCircleIcon /> : undefined}
1575-
variant={isPasswordValid as validationStatus}
1576-
>
1567+
<HelperTextItem variant={isPasswordValid as validationStatus}>
15771568
{isPasswordValidating
15781569
? 'Validating...'
15791570
: 'Password must be at least 12 characters and include one uppercase letter and one number.'}
@@ -1600,9 +1591,7 @@ export const Animations: FunctionComponent = () => {
16001591
sidebar={Sidebar}
16011592
isManagedSidebar
16021593
notificationDrawer={notificationDrawer}
1603-
onNotificationDrawerExpand={(
1604-
event: MouseEvent<Element, MouseEvent> | KeyboardEvent | TransitionEvent<Element>
1605-
) => focusDrawer(event)}
1594+
onNotificationDrawerExpand={(event) => focusDrawer(event)}
16061595
isNotificationDrawerExpanded={isDrawerExpanded}
16071596
skipToContent={PageSkipToContent}
16081597
// breadcrumb={PageBreadcrumb}

0 commit comments

Comments
 (0)