Skip to content

Commit 36f553a

Browse files
rhamiltoclaude
andcommitted
Migrate DeleteModal and related modals to modern PatternFly Modal
- Migrate DeleteModal from deprecated factory/modal components to modern PatternFly v6 Modal components - Create reusable ModalErrorContent component for error display - Update configure-count-modal and configure-machine-autoscaler-modal to use modern Modal components and ModalErrorContent - Fix button order in add-group-users-modal (Primary first, Cancel second) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 654a291 commit 36f553a

5 files changed

Lines changed: 193 additions & 114 deletions

File tree

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import type { FC, ReactNode } from 'react';
2+
import { HelperText, HelperTextItem } from '@patternfly/react-core';
3+
4+
export interface ModalErrorContentProps {
5+
/** The error message to display */
6+
errorMessage?: ReactNode;
7+
/** Optional additional CSS class names */
8+
className?: string;
9+
/** Optional data-test attribute for testing */
10+
'data-test'?: string;
11+
}
12+
13+
/**
14+
* Displays an error message in a modal footer using PatternFly HelperText.
15+
*
16+
* @example
17+
* ```tsx
18+
* <ModalFooter>
19+
* <ModalErrorContent errorMessage={errorMessage} />
20+
* {/* modal footer buttons *\/}
21+
* </ModalFooter>
22+
* ```
23+
*/
24+
export const ModalErrorContent: FC<ModalErrorContentProps> = ({
25+
errorMessage,
26+
className = 'pf-v6-u-w-100 pf-v6-u-mb-md',
27+
'data-test': dataTest = 'modal-error',
28+
}) => {
29+
if (!errorMessage) {
30+
return null;
31+
}
32+
33+
return (
34+
<HelperText isLiveRegion className={className}>
35+
<HelperTextItem variant="error" data-test={dataTest}>
36+
{errorMessage}
37+
</HelperTextItem>
38+
</HelperText>
39+
);
40+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './ModalErrorContent';

frontend/public/components/modals/configure-count-modal.tsx

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
import * as _ from 'lodash';
22
import { useTranslation } from 'react-i18next';
3-
import { useState, useCallback } from 'react';
3+
import { useState, useCallback, useEffect } from 'react';
44
import {
55
Modal,
66
ModalHeader,
77
ModalBody,
88
ModalFooter,
99
Button,
10-
HelperText,
11-
HelperTextItem,
1210
FormGroup,
1311
Form,
1412
} from '@patternfly/react-core';
@@ -18,6 +16,7 @@ import { k8sPatchResource } from '@console/dynamic-plugin-sdk/src/utils/k8s';
1816
import { K8sResourceKind, K8sModel } from '../../module/k8s';
1917
import { NumberSpinner, NumberSpinnerProps } from '../utils/number-spinner';
2018
import { usePromiseHandler } from '@console/shared/src/hooks/promise-handler';
19+
import { ModalErrorContent } from '@console/shared/src/components/modal-error-content';
2120

2221
export const ConfigureCountModal: OverlayComponent<ConfigureCountModalProps> = (props) => {
2322
const {
@@ -43,6 +42,13 @@ export const ConfigureCountModal: OverlayComponent<ConfigureCountModalProps> = (
4342
const { t } = useTranslation();
4443
const [handlePromise, inProgress, errorMessage] = usePromiseHandler();
4544

45+
// Move focus away from the triggering element to prevent aria-hidden warning
46+
useEffect(() => {
47+
if (document.activeElement instanceof HTMLElement) {
48+
document.activeElement.blur();
49+
}
50+
}, []);
51+
4652
const submit = useCallback(
4753
(e) => {
4854
e.preventDefault();
@@ -90,7 +96,7 @@ export const ConfigureCountModal: OverlayComponent<ConfigureCountModalProps> = (
9096
description={messageKey ? t(messageKey, messageVariablesSafe) : message}
9197
/>
9298
<ModalBody>
93-
<Form>
99+
<Form id="configure-count-form" onSubmit={submit}>
94100
<FormGroup>
95101
<NumberSpinner
96102
value={value}
@@ -100,21 +106,17 @@ export const ConfigureCountModal: OverlayComponent<ConfigureCountModalProps> = (
100106
required
101107
min={0}
102108
/>
103-
{errorMessage && (
104-
<HelperText isLiveRegion className="pf-v6-u-mt-md">
105-
<HelperTextItem variant="error">{errorMessage}</HelperTextItem>
106-
</HelperText>
107-
)}
108109
</FormGroup>
109110
</Form>
110111
</ModalBody>
111-
<ModalFooter>
112-
<Button variant="secondary" onClick={closeOverlay} type="button">
113-
{t('public~Cancel')}
114-
</Button>
115-
<Button variant="primary" isLoading={inProgress} onClick={submit}>
112+
<ModalFooter className="pf-v6-u-flex-wrap">
113+
<ModalErrorContent errorMessage={errorMessage} />
114+
<Button variant="primary" type="submit" form="configure-count-form" isLoading={inProgress}>
116115
{buttonTextKey ? t(buttonTextKey, buttonTextVariables) : buttonText}
117116
</Button>
117+
<Button variant="link" onClick={closeOverlay} type="button">
118+
{t('public~Cancel')}
119+
</Button>
118120
</ModalFooter>
119121
</Modal>
120122
);

frontend/public/components/modals/configure-machine-autoscaler-modal.tsx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import {
88
ModalBody,
99
ModalFooter,
1010
Button,
11-
HelperText,
12-
HelperTextItem,
1311
FormGroup,
1412
Form,
1513
} from '@patternfly/react-core';
@@ -20,6 +18,7 @@ import { resourcePathFromModel } from '../utils/resource-link';
2018
import { K8sResourceKind } from '../../module/k8s';
2119
import { k8sCreateResource } from '@console/dynamic-plugin-sdk/src/utils/k8s';
2220
import { usePromiseHandler } from '@console/shared/src/hooks/promise-handler';
21+
import { ModalErrorContent } from '@console/shared/src/components/modal-error-content';
2322

2423
export const ConfigureMachineAutoscalerModal: OverlayComponent<ConfigureMachineAutoscalerModalProps> = ({
2524
machineSet,
@@ -116,7 +115,7 @@ export const ConfigureMachineAutoscalerModal: OverlayComponent<ConfigureMachineA
116115
description={t('public~This will automatically scale machine set {{ name }}.', { name })}
117116
/>
118117
<ModalBody>
119-
<Form>
118+
<Form id="create-machineautoscaler-form">
120119
<FormGroup label={t('public~Minimum replicas:')} fieldId="min-replicas" isRequired>
121120
<NumberSpinner
122121
value={minReplicas}
@@ -134,20 +133,21 @@ export const ConfigureMachineAutoscalerModal: OverlayComponent<ConfigureMachineA
134133
required
135134
/>
136135
</FormGroup>
137-
{errorMessage && (
138-
<HelperText isLiveRegion className="pf-v6-u-mt-md">
139-
<HelperTextItem variant="error">{errorMessage}</HelperTextItem>
140-
</HelperText>
141-
)}
142136
</Form>
143137
</ModalBody>
144-
<ModalFooter>
145-
<Button variant="secondary" onClick={closeOverlay || cancelProp} type="button">
146-
{t('public~Cancel')}
147-
</Button>
148-
<Button variant="primary" isLoading={inProgress} onClick={submit}>
138+
<ModalFooter className="pf-v6-u-flex-wrap">
139+
<ModalErrorContent errorMessage={errorMessage} />
140+
<Button
141+
variant="primary"
142+
isLoading={inProgress}
143+
onClick={submit}
144+
form="create-machineautoscaler-form"
145+
>
149146
{t('public~Create')}
150147
</Button>
148+
<Button variant="link" onClick={closeOverlay || cancelProp} type="button">
149+
{t('public~Cancel')}
150+
</Button>
151151
</ModalFooter>
152152
</Modal>
153153
);

0 commit comments

Comments
 (0)