From 364e2226ee24bfd6d3d4e738ac5eae9eb4fd5cc7 Mon Sep 17 00:00:00 2001
From: Steve Goodwin
Date: Tue, 20 Jan 2026 13:45:01 -0500
Subject: [PATCH 1/9] Migrate DeleteHPAModal and ConsolePluginModal from
createModalLauncher to useOverlay Assisted by: Claude Code
---
.../src/actions/creators/hpa-factory.ts | 124 +++++++++---------
.../ConsoleOperatorConfig.tsx | 6 +-
.../src/components/hpa/DeleteHPAModal.tsx | 27 +++-
.../src/components/hpa/index.ts | 11 +-
.../components/modals/ConsolePluginModal.tsx | 52 +++++---
.../src/components/modals/index.ts | 2 +-
.../src/components/clusterserviceversion.tsx | 6 +-
7 files changed, 137 insertions(+), 91 deletions(-)
diff --git a/frontend/packages/console-app/src/actions/creators/hpa-factory.ts b/frontend/packages/console-app/src/actions/creators/hpa-factory.ts
index 7ad609ca5a..bc064bb5c0 100644
--- a/frontend/packages/console-app/src/actions/creators/hpa-factory.ts
+++ b/frontend/packages/console-app/src/actions/creators/hpa-factory.ts
@@ -1,6 +1,7 @@
import { useMemo } from 'react';
import i18next from 'i18next';
import type { Action } from '@console/dynamic-plugin-sdk';
+import { useOverlay } from '@console/dynamic-plugin-sdk/src/app/modal-support/useOverlay';
import { useK8sWatchResources } from '@console/internal/components/utils/k8s-watch-hook';
import { HorizontalPodAutoscalerModel } from '@console/internal/models';
import type {
@@ -12,84 +13,23 @@ import type {
import { referenceForModel } from '@console/internal/module/k8s';
import type { ClusterServiceVersionKind } from '@console/operator-lifecycle-manager';
import { ClusterServiceVersionModel } from '@console/operator-lifecycle-manager';
-import deleteHPAModal from '@console/shared/src/components/hpa/DeleteHPAModal';
+import { LazyDeleteHPAModalOverlay } from '@console/shared/src/components/hpa';
import { isHelmResource } from '@console/shared/src/utils/helm-utils';
import { doesHpaMatch } from '@console/shared/src/utils/hpa-utils';
import { isOperatorBackedService } from '@console/shared/src/utils/operator-utils';
-import type { ResourceActionFactory } from './types';
const hpaRoute = (
{ metadata: { name = '', namespace = '' } = {} }: K8sResourceCommon,
kind: K8sKind,
) => `/workload-hpa/ns/${namespace}/${referenceForModel(kind)}/${name}`;
-export const HpaActionFactory: ResourceActionFactory = {
- AddHorizontalPodAutoScaler: (kind: K8sKind, obj: K8sResourceKind) => ({
- id: 'add-hpa',
- label: i18next.t('console-app~Add HorizontalPodAutoscaler'),
- cta: { href: hpaRoute(obj, kind) },
- insertBefore: 'add-pdb',
- accessReview: {
- group: HorizontalPodAutoscalerModel.apiGroup,
- resource: HorizontalPodAutoscalerModel.plural,
- namespace: obj.metadata?.namespace,
- verb: 'create',
- },
- }),
- EditHorizontalPodAutoScaler: (kind: K8sKind, obj: K8sResourceCommon) => ({
- id: 'edit-hpa',
- label: i18next.t('console-app~Edit HorizontalPodAutoscaler'),
- cta: { href: hpaRoute(obj, kind) },
- insertBefore: 'add-pdb',
- accessReview: {
- group: HorizontalPodAutoscalerModel.apiGroup,
- resource: HorizontalPodAutoscalerModel.plural,
- namespace: obj.metadata?.namespace,
- verb: 'update',
- },
- }),
- DeleteHorizontalPodAutoScaler: (
- kind: K8sKind,
- obj: K8sResourceCommon,
- relatedHPA: HorizontalPodAutoscalerKind,
- ) => ({
- id: 'delete-hpa',
- label: i18next.t('console-app~Remove HorizontalPodAutoscaler'),
- insertBefore: 'delete-pdb',
- cta: () => {
- deleteHPAModal({
- workload: obj,
- hpa: relatedHPA,
- });
- },
- accessReview: {
- group: HorizontalPodAutoscalerModel.apiGroup,
- resource: HorizontalPodAutoscalerModel.plural,
- namespace: obj.metadata?.namespace,
- verb: 'delete',
- },
- }),
-};
-
-export const getHpaActions = (
- kind: K8sKind,
- obj: K8sResourceKind,
- relatedHPAs: K8sResourceKind[],
-): Action[] => {
- if (relatedHPAs.length === 0) return [HpaActionFactory.AddHorizontalPodAutoScaler(kind, obj)];
-
- return [
- HpaActionFactory.EditHorizontalPodAutoScaler(kind, obj),
- HpaActionFactory.DeleteHorizontalPodAutoScaler(kind, obj, relatedHPAs[0]),
- ];
-};
-
type DeploymentActionExtraResources = {
hpas: HorizontalPodAutoscalerKind[];
csvs: ClusterServiceVersionKind[];
};
export const useHPAActions = (kindObj: K8sKind, resource: K8sResourceKind) => {
+ const launchOverlay = useOverlay();
const namespace = resource?.metadata?.namespace;
const watchedResources = useMemo(
@@ -121,9 +61,63 @@ export const useHPAActions = (kindObj: K8sKind, resource: K8sResourceKind) => {
[extraResources.csvs.data, resource],
);
- const result = useMemo<[Action[], HorizontalPodAutoscalerKind[]]>(() => {
- return [supportsHPA ? getHpaActions(kindObj, resource, relatedHPAs) : [], relatedHPAs];
+ const actions = useMemo(() => {
+ if (!supportsHPA) return [];
+
+ if (relatedHPAs.length === 0) {
+ return [
+ {
+ id: 'add-hpa',
+ label: i18next.t('console-app~Add HorizontalPodAutoscaler'),
+ cta: { href: hpaRoute(resource, kindObj) },
+ insertBefore: 'add-pdb',
+ accessReview: {
+ group: HorizontalPodAutoscalerModel.apiGroup,
+ resource: HorizontalPodAutoscalerModel.plural,
+ namespace: resource.metadata?.namespace,
+ verb: 'create',
+ },
+ },
+ ];
+ }
+ return [
+ {
+ id: 'edit-hpa',
+ label: i18next.t('console-app~Edit HorizontalPodAutoscaler'),
+ cta: { href: hpaRoute(resource, kindObj) },
+ insertBefore: 'add-pdb',
+ accessReview: {
+ group: HorizontalPodAutoscalerModel.apiGroup,
+ resource: HorizontalPodAutoscalerModel.plural,
+ namespace: resource.metadata?.namespace,
+ verb: 'update',
+ },
+ },
+ {
+ id: 'delete-hpa',
+ label: i18next.t('console-app~Remove HorizontalPodAutoscaler'),
+ insertBefore: 'delete-pdb',
+ cta: () => {
+ launchOverlay(LazyDeleteHPAModalOverlay, {
+ workload: resource,
+ hpa: relatedHPAs[0],
+ });
+ },
+ accessReview: {
+ group: HorizontalPodAutoscalerModel.apiGroup,
+ resource: HorizontalPodAutoscalerModel.plural,
+ namespace: resource.metadata?.namespace,
+ verb: 'delete',
+ },
+ },
+ ];
+ // missing launchModal dependency, that causes max depth exceeded error
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [kindObj, relatedHPAs, resource, supportsHPA]);
+ const result = useMemo<[Action[], HorizontalPodAutoscalerKind[]]>(() => {
+ return [actions, relatedHPAs];
+ }, [actions, relatedHPAs]);
+
return result;
};
diff --git a/frontend/packages/console-app/src/components/console-operator/ConsoleOperatorConfig.tsx b/frontend/packages/console-app/src/components/console-operator/ConsoleOperatorConfig.tsx
index 296805d7ce..e537b8c80c 100644
--- a/frontend/packages/console-app/src/components/console-operator/ConsoleOperatorConfig.tsx
+++ b/frontend/packages/console-app/src/components/console-operator/ConsoleOperatorConfig.tsx
@@ -11,6 +11,7 @@ import { Link } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import type { WatchK8sResource } from '@console/dynamic-plugin-sdk';
import { useAccessReview } from '@console/dynamic-plugin-sdk';
+import { useOverlay } from '@console/dynamic-plugin-sdk/src/app/modal-support/useOverlay';
import {
getGroupVersionKindForModel,
getReferenceForModel,
@@ -35,7 +36,7 @@ import { referenceForModel } from '@console/internal/module/k8s';
import type { RootState } from '@console/internal/redux';
import { usePluginInfo } from '@console/plugin-sdk/src/api/usePluginInfo';
import PaneBody from '@console/shared/src/components/layout/PaneBody';
-import { consolePluginModal } from '@console/shared/src/components/modals/ConsolePluginModal';
+import { LazyConsolePluginModalOverlay } from '@console/shared/src/components/modals';
import {
GreenCheckCircleIcon,
YellowExclamationTriangleIcon,
@@ -102,6 +103,7 @@ export const ConsolePluginEnabledStatus: FC = (
enabled,
}) => {
const { t } = useTranslation('console-app');
+ const launchModal = useOverlay();
const {
consoleOperatorConfig,
@@ -121,7 +123,7 @@ export const ConsolePluginEnabledStatus: FC = (
type="button"
isInline
onClick={() =>
- consolePluginModal({
+ launchModal(LazyConsolePluginModalOverlay, {
consoleOperatorConfig,
pluginName,
trusted: false,
diff --git a/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx b/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx
index 309527cc92..57534ab73e 100644
--- a/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx
+++ b/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx
@@ -5,11 +5,12 @@ import { ExclamationTriangleIcon } from '@patternfly/react-icons/dist/esm/icons/
import { t_global_icon_color_status_warning_default as warningColor } from '@patternfly/react-tokens';
import { useTranslation } from 'react-i18next';
import type { ModalComponentProps } from '@console/internal/components/factory/modal';
+import { OverlayComponent } from '@console/dynamic-plugin-sdk/src/app/modal-support/OverlayProvider';
import {
- createModalLauncher,
ModalBody,
ModalSubmitFooter,
ModalTitle,
+ ModalWrapper,
} from '@console/internal/components/factory/modal';
import { LoadingInline } from '@console/internal/components/utils/status-box';
import { HorizontalPodAutoscalerModel } from '@console/internal/models';
@@ -21,7 +22,7 @@ type DeleteHPAModalProps = ModalComponentProps & {
workload: K8sResourceCommon;
};
-const DeleteHPAModal: FC = ({ close, hpa, workload }) => {
+const DeleteHPAModal: FC = ({ close, cancel, hpa, workload }) => {
const [submitError, setSubmitError] = useState(null);
const [isSubmitting, setIsSubmitting] = useState(false);
const { t } = useTranslation();
@@ -79,11 +80,29 @@ const DeleteHPAModal: FC = ({ close, hpa, workload }) => {
submitText={t('console-shared~Remove')}
submitDanger
submitDisabled={!!submitError}
- cancel={close}
+ cancel={cancel}
/>
);
};
-export default createModalLauncher(DeleteHPAModal);
+type DeleteHPAModalProviderProps = {
+ hpa: HorizontalPodAutoscalerKind;
+ workload: K8sResourceCommon;
+};
+
+const DeleteHPAModalProvider: OverlayComponent = (props) => {
+ return (
+
+
+
+ );
+};
+
+export default DeleteHPAModalProvider;
diff --git a/frontend/packages/console-shared/src/components/hpa/index.ts b/frontend/packages/console-shared/src/components/hpa/index.ts
index fc131d9b54..53549d3234 100644
--- a/frontend/packages/console-shared/src/components/hpa/index.ts
+++ b/frontend/packages/console-shared/src/components/hpa/index.ts
@@ -1 +1,10 @@
-export { default as deleteHPAModal } from './DeleteHPAModal';
+import { lazy } from 'react';
+
+export { DeleteHPAModalOverlay } from './DeleteHPAModal';
+
+// Lazy-loaded OverlayComponent for DeleteHPAModal
+export const LazyDeleteHPAModalOverlay = lazy(() =>
+ import('./DeleteHPAModal' /* webpackChunkName: "delete-hpa-modal" */).then((m) => ({
+ default: m.DeleteHPAModalOverlay,
+ })),
+);
\ No newline at end of file
diff --git a/frontend/packages/console-shared/src/components/modals/ConsolePluginModal.tsx b/frontend/packages/console-shared/src/components/modals/ConsolePluginModal.tsx
index 84fe982697..e5476bd21e 100644
--- a/frontend/packages/console-shared/src/components/modals/ConsolePluginModal.tsx
+++ b/frontend/packages/console-shared/src/components/modals/ConsolePluginModal.tsx
@@ -1,11 +1,11 @@
import { useState } from 'react';
-import { Form } from '@patternfly/react-core';
import { useTranslation } from 'react-i18next';
+import { OverlayComponent } from '@console/dynamic-plugin-sdk/src/app/modal-support/OverlayProvider';
import {
- createModalLauncher,
ModalTitle,
ModalBody,
ModalSubmitFooter,
+ ModalWrapper,
} from '@console/internal/components/factory/modal';
import { ConsoleOperatorConfigModel } from '@console/internal/models';
import type { K8sResourceKind } from '@console/internal/module/k8s';
@@ -49,19 +49,17 @@ export const ConsolePluginModal = (props: ConsolePluginModalProps) => {
'console-shared~This console plugin provides a custom interface that can be included in the console. Updating the enablement of this console plugin will prompt for the console to be refreshed once it has been updated. Make sure you trust this console plugin before enabling.',
)}
-
+
+
{
);
};
-export const consolePluginModal = createModalLauncher(ConsolePluginModal);
+type ConsolePluginModalProviderProps = {
+ consoleOperatorConfig: K8sResourceKind;
+ csvPluginsCount?: number;
+ pluginName: string;
+ trusted: boolean;
+};
+
+const ConsolePluginModalProvider: OverlayComponent = (props) => {
+ return (
+
+
+
+ );
+};
+
+export default ConsolePluginModalProvider;
export type ConsolePluginModalProps = {
consoleOperatorConfig: K8sResourceKind;
diff --git a/frontend/packages/console-shared/src/components/modals/index.ts b/frontend/packages/console-shared/src/components/modals/index.ts
index ac902b242d..53f05c1275 100644
--- a/frontend/packages/console-shared/src/components/modals/index.ts
+++ b/frontend/packages/console-shared/src/components/modals/index.ts
@@ -1,6 +1,6 @@
export const consolePluginModal = (props) =>
import('./ConsolePluginModal' /* webpackChunkName: "shared-modals" */).then((m) =>
- m.consolePluginModal(props),
+ m.default(props),
);
export const deleteResourceModal = (props) =>
diff --git a/frontend/packages/operator-lifecycle-manager/src/components/clusterserviceversion.tsx b/frontend/packages/operator-lifecycle-manager/src/components/clusterserviceversion.tsx
index 8429d635d4..00964b06de 100644
--- a/frontend/packages/operator-lifecycle-manager/src/components/clusterserviceversion.tsx
+++ b/frontend/packages/operator-lifecycle-manager/src/components/clusterserviceversion.tsx
@@ -30,6 +30,7 @@ import {
useAccessReviewAllowed,
useAccessReview,
} from '@console/dynamic-plugin-sdk';
+import { useOverlay } from '@console/dynamic-plugin-sdk/src/app/modal-support/useOverlay';
import { getGroupVersionKindForModel } from '@console/dynamic-plugin-sdk/src/lib-core';
import { Conditions, ConditionTypes } from '@console/internal/components/conditions';
import { ResourceEventStream } from '@console/internal/components/events';
@@ -66,7 +67,7 @@ import { DocumentTitle } from '@console/shared/src/components/document-title/Doc
import { withFallback } from '@console/shared/src/components/error';
import PaneBody from '@console/shared/src/components/layout/PaneBody';
import { ExternalLink } from '@console/shared/src/components/links/ExternalLink';
-import { consolePluginModal } from '@console/shared/src/components/modals';
+import ConsolePluginModalProvider from '@console/shared/src/components/modals/ConsolePluginModal';
import { RedExclamationCircleIcon } from '@console/shared/src/components/status/icons';
import { CONSOLE_OPERATOR_CONFIG_NAME } from '@console/shared/src/constants';
import { useActiveNamespace } from '@console/shared/src/hooks/redux-selectors';
@@ -228,6 +229,7 @@ const ManagedNamespaces: FC = ({ obj }) => {
};
const ConsolePlugins: FC = ({ csvPlugins, trusted }) => {
+ const launchOverlay = useOverlay();
const console: WatchK8sResource = {
kind: referenceForModel(ConsoleOperatorConfigModel),
isList: false,
@@ -262,7 +264,7 @@ const ConsolePlugins: FC = ({ csvPlugins, trusted }) => {
type="button"
isInline
onClick={() =>
- consolePluginModal({
+ launchOverlay(ConsolePluginModalProvider, {
consoleOperatorConfig,
pluginName,
trusted,
From 633e201c4949002c2b3e0987857f1b078a31aa8f Mon Sep 17 00:00:00 2001
From: Steve Goodwin
Date: Fri, 30 Jan 2026 17:21:25 -0500
Subject: [PATCH 2/9] Address comments
Assisted by: Claude Code
---
.../console-shared/src/components/hpa/DeleteHPAModal.tsx | 2 +-
.../packages/console-shared/src/components/hpa/index.ts | 2 +-
.../src/components/modals/ConsolePluginModal.tsx | 6 +++---
.../packages/console-shared/src/components/modals/index.ts | 2 +-
.../src/components/clusterserviceversion.tsx | 4 ++--
5 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx b/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx
index 57534ab73e..a156e6b4ca 100644
--- a/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx
+++ b/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx
@@ -105,4 +105,4 @@ const DeleteHPAModalProvider: OverlayComponent = (p
);
};
-export default DeleteHPAModalProvider;
+export { DeleteHPAModalProvider };
diff --git a/frontend/packages/console-shared/src/components/hpa/index.ts b/frontend/packages/console-shared/src/components/hpa/index.ts
index 53549d3234..43a3b40d15 100644
--- a/frontend/packages/console-shared/src/components/hpa/index.ts
+++ b/frontend/packages/console-shared/src/components/hpa/index.ts
@@ -7,4 +7,4 @@ export const LazyDeleteHPAModalOverlay = lazy(() =>
import('./DeleteHPAModal' /* webpackChunkName: "delete-hpa-modal" */).then((m) => ({
default: m.DeleteHPAModalOverlay,
})),
-);
\ No newline at end of file
+);
diff --git a/frontend/packages/console-shared/src/components/modals/ConsolePluginModal.tsx b/frontend/packages/console-shared/src/components/modals/ConsolePluginModal.tsx
index e5476bd21e..4ed2c4d4b0 100644
--- a/frontend/packages/console-shared/src/components/modals/ConsolePluginModal.tsx
+++ b/frontend/packages/console-shared/src/components/modals/ConsolePluginModal.tsx
@@ -72,14 +72,14 @@ export const ConsolePluginModal = (props: ConsolePluginModalProps) => {
);
};
-type ConsolePluginModalProviderProps = {
+type ConsolePluginModalOverlayProps = {
consoleOperatorConfig: K8sResourceKind;
csvPluginsCount?: number;
pluginName: string;
trusted: boolean;
};
-const ConsolePluginModalProvider: OverlayComponent = (props) => {
+const ConsolePluginModalOverlay: OverlayComponent = (props) => {
return (
import('./ConsolePluginModal' /* webpackChunkName: "shared-modals" */).then((m) =>
- m.default(props),
+ m.ConsolePluginModalOverlay(props),
);
export const deleteResourceModal = (props) =>
diff --git a/frontend/packages/operator-lifecycle-manager/src/components/clusterserviceversion.tsx b/frontend/packages/operator-lifecycle-manager/src/components/clusterserviceversion.tsx
index 00964b06de..d74b8ade16 100644
--- a/frontend/packages/operator-lifecycle-manager/src/components/clusterserviceversion.tsx
+++ b/frontend/packages/operator-lifecycle-manager/src/components/clusterserviceversion.tsx
@@ -67,7 +67,7 @@ import { DocumentTitle } from '@console/shared/src/components/document-title/Doc
import { withFallback } from '@console/shared/src/components/error';
import PaneBody from '@console/shared/src/components/layout/PaneBody';
import { ExternalLink } from '@console/shared/src/components/links/ExternalLink';
-import ConsolePluginModalProvider from '@console/shared/src/components/modals/ConsolePluginModal';
+import { ConsolePluginModalOverlay } from '@console/shared/src/components/modals/ConsolePluginModal';
import { RedExclamationCircleIcon } from '@console/shared/src/components/status/icons';
import { CONSOLE_OPERATOR_CONFIG_NAME } from '@console/shared/src/constants';
import { useActiveNamespace } from '@console/shared/src/hooks/redux-selectors';
@@ -264,7 +264,7 @@ const ConsolePlugins: FC = ({ csvPlugins, trusted }) => {
type="button"
isInline
onClick={() =>
- launchOverlay(ConsolePluginModalProvider, {
+ launchOverlay(ConsolePluginModalOverlay, {
consoleOperatorConfig,
pluginName,
trusted,
From d51fbb94418d47a6a7bdcbb26b72f066a7f7a54f Mon Sep 17 00:00:00 2001
From: Steve Goodwin
Date: Tue, 3 Feb 2026 15:25:36 -0500
Subject: [PATCH 3/9] Batch renaming for consistency. Assisted-by Claude
---
.../console-app/src/actions/creators/hpa-factory.ts | 4 ++--
.../console-shared/src/components/hpa/DeleteHPAModal.tsx | 6 +++---
.../src/components/clusterserviceversion.tsx | 4 ++--
3 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/frontend/packages/console-app/src/actions/creators/hpa-factory.ts b/frontend/packages/console-app/src/actions/creators/hpa-factory.ts
index bc064bb5c0..f0da79dcca 100644
--- a/frontend/packages/console-app/src/actions/creators/hpa-factory.ts
+++ b/frontend/packages/console-app/src/actions/creators/hpa-factory.ts
@@ -29,7 +29,7 @@ type DeploymentActionExtraResources = {
};
export const useHPAActions = (kindObj: K8sKind, resource: K8sResourceKind) => {
- const launchOverlay = useOverlay();
+ const launchModal = useOverlay();
const namespace = resource?.metadata?.namespace;
const watchedResources = useMemo(
@@ -111,7 +111,7 @@ export const useHPAActions = (kindObj: K8sKind, resource: K8sResourceKind) => {
},
},
];
- // missing launchModal dependency, that causes max depth exceeded error
+ // Missing launchModal dependency causes max depth exceeded error
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [kindObj, relatedHPAs, resource, supportsHPA]);
diff --git a/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx b/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx
index a156e6b4ca..4e1a0664d2 100644
--- a/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx
+++ b/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx
@@ -87,12 +87,12 @@ const DeleteHPAModal: FC = ({ close, cancel, hpa, workload
);
};
-type DeleteHPAModalProviderProps = {
+type DeleteHPAModalOverlayProps = {
hpa: HorizontalPodAutoscalerKind;
workload: K8sResourceCommon;
};
-const DeleteHPAModalProvider: OverlayComponent = (props) => {
+const DeleteHPAModalOverlay: OverlayComponent = (props) => {
return (
= (p
);
};
-export { DeleteHPAModalProvider };
+export { DeleteHPAModalOverlay };
diff --git a/frontend/packages/operator-lifecycle-manager/src/components/clusterserviceversion.tsx b/frontend/packages/operator-lifecycle-manager/src/components/clusterserviceversion.tsx
index d74b8ade16..6bb1811f1c 100644
--- a/frontend/packages/operator-lifecycle-manager/src/components/clusterserviceversion.tsx
+++ b/frontend/packages/operator-lifecycle-manager/src/components/clusterserviceversion.tsx
@@ -229,7 +229,7 @@ const ManagedNamespaces: FC = ({ obj }) => {
};
const ConsolePlugins: FC = ({ csvPlugins, trusted }) => {
- const launchOverlay = useOverlay();
+ const launchModal = useOverlay();
const console: WatchK8sResource = {
kind: referenceForModel(ConsoleOperatorConfigModel),
isList: false,
@@ -264,7 +264,7 @@ const ConsolePlugins: FC = ({ csvPlugins, trusted }) => {
type="button"
isInline
onClick={() =>
- launchOverlay(ConsolePluginModalOverlay, {
+ launchModal(ConsolePluginModalOverlay, {
consoleOperatorConfig,
pluginName,
trusted,
From f34e44f4bf1ef71b731ef9ef11f34c45dabc03d2 Mon Sep 17 00:00:00 2001
From: Steve Goodwin
Date: Tue, 3 Feb 2026 18:11:08 -0500
Subject: [PATCH 4/9] Include launchModal in dependency array
---
.../packages/console-app/src/actions/creators/hpa-factory.ts | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/frontend/packages/console-app/src/actions/creators/hpa-factory.ts b/frontend/packages/console-app/src/actions/creators/hpa-factory.ts
index f0da79dcca..f8aad6d3d4 100644
--- a/frontend/packages/console-app/src/actions/creators/hpa-factory.ts
+++ b/frontend/packages/console-app/src/actions/creators/hpa-factory.ts
@@ -111,9 +111,7 @@ export const useHPAActions = (kindObj: K8sKind, resource: K8sResourceKind) => {
},
},
];
- // Missing launchModal dependency causes max depth exceeded error
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [kindObj, relatedHPAs, resource, supportsHPA]);
+ }, [kindObj, launchModal, relatedHPAs, resource, supportsHPA]);
const result = useMemo<[Action[], HorizontalPodAutoscalerKind[]]>(() => {
return [actions, relatedHPAs];
From ee97039ee0cd9f9987685a67f3bbb01417730595 Mon Sep 17 00:00:00 2001
From: Steve Goodwin
Date: Thu, 5 Feb 2026 16:23:17 -0500
Subject: [PATCH 5/9] Revert clusterserviceversion.tsx changes to avoid
conflict with PR #15968
The ConsolePluginModal consumer changes in clusterserviceversion.tsx are
being migrated in PR #15968 (OLM modals migration). This PR should only
focus on the modal component migrations (DeleteHPAModal and ConsolePluginModal).
The file now uses the backwards-compatible consolePluginModal() function
which internally calls the new ConsolePluginModalOverlay pattern.
Assisted by: Claude Code
---
.../src/components/clusterserviceversion.tsx | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/frontend/packages/operator-lifecycle-manager/src/components/clusterserviceversion.tsx b/frontend/packages/operator-lifecycle-manager/src/components/clusterserviceversion.tsx
index 6bb1811f1c..8429d635d4 100644
--- a/frontend/packages/operator-lifecycle-manager/src/components/clusterserviceversion.tsx
+++ b/frontend/packages/operator-lifecycle-manager/src/components/clusterserviceversion.tsx
@@ -30,7 +30,6 @@ import {
useAccessReviewAllowed,
useAccessReview,
} from '@console/dynamic-plugin-sdk';
-import { useOverlay } from '@console/dynamic-plugin-sdk/src/app/modal-support/useOverlay';
import { getGroupVersionKindForModel } from '@console/dynamic-plugin-sdk/src/lib-core';
import { Conditions, ConditionTypes } from '@console/internal/components/conditions';
import { ResourceEventStream } from '@console/internal/components/events';
@@ -67,7 +66,7 @@ import { DocumentTitle } from '@console/shared/src/components/document-title/Doc
import { withFallback } from '@console/shared/src/components/error';
import PaneBody from '@console/shared/src/components/layout/PaneBody';
import { ExternalLink } from '@console/shared/src/components/links/ExternalLink';
-import { ConsolePluginModalOverlay } from '@console/shared/src/components/modals/ConsolePluginModal';
+import { consolePluginModal } from '@console/shared/src/components/modals';
import { RedExclamationCircleIcon } from '@console/shared/src/components/status/icons';
import { CONSOLE_OPERATOR_CONFIG_NAME } from '@console/shared/src/constants';
import { useActiveNamespace } from '@console/shared/src/hooks/redux-selectors';
@@ -229,7 +228,6 @@ const ManagedNamespaces: FC = ({ obj }) => {
};
const ConsolePlugins: FC = ({ csvPlugins, trusted }) => {
- const launchModal = useOverlay();
const console: WatchK8sResource = {
kind: referenceForModel(ConsoleOperatorConfigModel),
isList: false,
@@ -264,7 +262,7 @@ const ConsolePlugins: FC = ({ csvPlugins, trusted }) => {
type="button"
isInline
onClick={() =>
- launchModal(ConsolePluginModalOverlay, {
+ consolePluginModal({
consoleOperatorConfig,
pluginName,
trusted,
From 8849858458fe5c9ec2ef15d086ad7d33213a34b6 Mon Sep 17 00:00:00 2001
From: Steve Goodwin
Date: Thu, 5 Feb 2026 16:29:46 -0500
Subject: [PATCH 6/9] Fix modal pattern violations to comply with migration
guide
Updated DeleteHPAModal and ConsolePluginModal to follow the patterns
from PR #15939 and the modal-migration-guide.md:
1. Export Pattern: Changed from const + export { } to export const
2. Type Positioning: Moved overlay props types to bottom of files
3. ModalComponentProps: Updated ConsolePluginModalProps to extend it
Changes:
- DeleteHPAModal.tsx: export const pattern, type at bottom
- ConsolePluginModal.tsx: export const pattern, extends ModalComponentProps,
removed explicit cancel/close props, moved overlay props to bottom
Assisted by: Claude Code
---
.../src/components/hpa/DeleteHPAModal.tsx | 12 ++++------
.../components/modals/ConsolePluginModal.tsx | 23 +++++++++----------
2 files changed, 16 insertions(+), 19 deletions(-)
diff --git a/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx b/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx
index 4e1a0664d2..14d9c3cdca 100644
--- a/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx
+++ b/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx
@@ -87,12 +87,7 @@ const DeleteHPAModal: FC = ({ close, cancel, hpa, workload
);
};
-type DeleteHPAModalOverlayProps = {
- hpa: HorizontalPodAutoscalerKind;
- workload: K8sResourceCommon;
-};
-
-const DeleteHPAModalOverlay: OverlayComponent = (props) => {
+export const DeleteHPAModalOverlay: OverlayComponent = (props) => {
return (
= (pro
);
};
-export { DeleteHPAModalOverlay };
+type DeleteHPAModalOverlayProps = {
+ hpa: HorizontalPodAutoscalerKind;
+ workload: K8sResourceCommon;
+};
diff --git a/frontend/packages/console-shared/src/components/modals/ConsolePluginModal.tsx b/frontend/packages/console-shared/src/components/modals/ConsolePluginModal.tsx
index 4ed2c4d4b0..9843d8aa16 100644
--- a/frontend/packages/console-shared/src/components/modals/ConsolePluginModal.tsx
+++ b/frontend/packages/console-shared/src/components/modals/ConsolePluginModal.tsx
@@ -6,6 +6,7 @@ import {
ModalBody,
ModalSubmitFooter,
ModalWrapper,
+ ModalComponentProps,
} from '@console/internal/components/factory/modal';
import { ConsoleOperatorConfigModel } from '@console/internal/models';
import type { K8sResourceKind } from '@console/internal/module/k8s';
@@ -72,14 +73,9 @@ export const ConsolePluginModal = (props: ConsolePluginModalProps) => {
);
};
-type ConsolePluginModalOverlayProps = {
- consoleOperatorConfig: K8sResourceKind;
- csvPluginsCount?: number;
- pluginName: string;
- trusted: boolean;
-};
-
-const ConsolePluginModalOverlay: OverlayComponent = (props) => {
+export const ConsolePluginModalOverlay: OverlayComponent = (
+ props,
+) => {
return (
void;
- close?: () => void;
-};
+} & ModalComponentProps;
From d06d28c4c7ce6dd5f58c9ac24c8a5e5079cbec7c Mon Sep 17 00:00:00 2001
From: Steve Goodwin
Date: Tue, 10 Feb 2026 14:34:08 -0500
Subject: [PATCH 7/9] Add lazy loading to modals and remove duplicate types
---
.../src/components/hpa/DeleteHPAModal.tsx | 9 ++-------
.../src/components/modals/ConsolePluginModal.tsx | 11 +----------
.../console-shared/src/components/modals/index.ts | 12 ++++++++----
.../src/components/clusterserviceversion.tsx | 7 +++++--
4 files changed, 16 insertions(+), 23 deletions(-)
diff --git a/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx b/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx
index 14d9c3cdca..6d2fb3bf66 100644
--- a/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx
+++ b/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx
@@ -17,11 +17,6 @@ import { HorizontalPodAutoscalerModel } from '@console/internal/models';
import type { HorizontalPodAutoscalerKind, K8sResourceCommon } from '@console/internal/module/k8s';
import { k8sKill } from '@console/internal/module/k8s';
-type DeleteHPAModalProps = ModalComponentProps & {
- hpa: HorizontalPodAutoscalerKind;
- workload: K8sResourceCommon;
-};
-
const DeleteHPAModal: FC = ({ close, cancel, hpa, workload }) => {
const [submitError, setSubmitError] = useState(null);
const [isSubmitting, setIsSubmitting] = useState(false);
@@ -87,7 +82,7 @@ const DeleteHPAModal: FC = ({ close, cancel, hpa, workload
);
};
-export const DeleteHPAModalOverlay: OverlayComponent = (props) => {
+export const DeleteHPAModalOverlay: OverlayComponent = (props) => {
return (
);
};
-type DeleteHPAModalOverlayProps = {
+type DeleteHPAModalProps = ModalComponentProps & {
hpa: HorizontalPodAutoscalerKind;
workload: K8sResourceCommon;
};
diff --git a/frontend/packages/console-shared/src/components/modals/ConsolePluginModal.tsx b/frontend/packages/console-shared/src/components/modals/ConsolePluginModal.tsx
index 9843d8aa16..8d68615159 100644
--- a/frontend/packages/console-shared/src/components/modals/ConsolePluginModal.tsx
+++ b/frontend/packages/console-shared/src/components/modals/ConsolePluginModal.tsx
@@ -73,9 +73,7 @@ export const ConsolePluginModal = (props: ConsolePluginModalProps) => {
);
};
-export const ConsolePluginModalOverlay: OverlayComponent = (
- props,
-) => {
+export const ConsolePluginModalOverlay: OverlayComponent = (props) => {
return (
- import('./ConsolePluginModal' /* webpackChunkName: "shared-modals" */).then((m) =>
- m.ConsolePluginModalOverlay(props),
- );
+import { lazy } from 'react';
+
+// Lazy-loaded OverlayComponent for ConsolePluginModal
+export const LazyConsolePluginModalOverlay = lazy(() =>
+ import('./ConsolePluginModal' /* webpackChunkName: "shared-modals" */).then((m) => ({
+ default: m.ConsolePluginModalOverlay,
+ })),
+);
export const deleteResourceModal = (props) =>
import('./DeleteResourceModal' /* webpackChunkName: "shared-modals" */).then((m) =>
diff --git a/frontend/packages/operator-lifecycle-manager/src/components/clusterserviceversion.tsx b/frontend/packages/operator-lifecycle-manager/src/components/clusterserviceversion.tsx
index 8429d635d4..dbff87f9d3 100644
--- a/frontend/packages/operator-lifecycle-manager/src/components/clusterserviceversion.tsx
+++ b/frontend/packages/operator-lifecycle-manager/src/components/clusterserviceversion.tsx
@@ -30,6 +30,7 @@ import {
useAccessReviewAllowed,
useAccessReview,
} from '@console/dynamic-plugin-sdk';
+import { useOverlay } from '@console/dynamic-plugin-sdk/src/app/modal-support/useOverlay';
import { getGroupVersionKindForModel } from '@console/dynamic-plugin-sdk/src/lib-core';
import { Conditions, ConditionTypes } from '@console/internal/components/conditions';
import { ResourceEventStream } from '@console/internal/components/events';
@@ -66,7 +67,7 @@ import { DocumentTitle } from '@console/shared/src/components/document-title/Doc
import { withFallback } from '@console/shared/src/components/error';
import PaneBody from '@console/shared/src/components/layout/PaneBody';
import { ExternalLink } from '@console/shared/src/components/links/ExternalLink';
-import { consolePluginModal } from '@console/shared/src/components/modals';
+import { LazyConsolePluginModalOverlay } from '@console/shared/src/components/modals';
import { RedExclamationCircleIcon } from '@console/shared/src/components/status/icons';
import { CONSOLE_OPERATOR_CONFIG_NAME } from '@console/shared/src/constants';
import { useActiveNamespace } from '@console/shared/src/hooks/redux-selectors';
@@ -235,6 +236,7 @@ const ConsolePlugins: FC = ({ csvPlugins, trusted }) => {
};
const [consoleOperatorConfig] = useK8sWatchResource(console);
const { t } = useTranslation();
+ const launchModal = useOverlay();
const [canPatchConsoleOperatorConfig] = useAccessReview({
group: ConsoleOperatorConfigModel.apiGroup,
resource: ConsoleOperatorConfigModel.plural,
@@ -262,8 +264,9 @@ const ConsolePlugins: FC = ({ csvPlugins, trusted }) => {
type="button"
isInline
onClick={() =>
- consolePluginModal({
+ launchModal(LazyConsolePluginModalOverlay, {
consoleOperatorConfig,
+ csvPluginsCount,
pluginName,
trusted,
})
From e4f6d16a08fda79c74a54ec52532b1cfc8435c84 Mon Sep 17 00:00:00 2001
From: Steve Goodwin
Date: Tue, 24 Feb 2026 12:24:17 -0500
Subject: [PATCH 8/9] Fix rebase error
---
.../packages/console-app/src/actions/creators/hpa-factory.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/frontend/packages/console-app/src/actions/creators/hpa-factory.ts b/frontend/packages/console-app/src/actions/creators/hpa-factory.ts
index f8aad6d3d4..4dc2224b4b 100644
--- a/frontend/packages/console-app/src/actions/creators/hpa-factory.ts
+++ b/frontend/packages/console-app/src/actions/creators/hpa-factory.ts
@@ -98,7 +98,7 @@ export const useHPAActions = (kindObj: K8sKind, resource: K8sResourceKind) => {
label: i18next.t('console-app~Remove HorizontalPodAutoscaler'),
insertBefore: 'delete-pdb',
cta: () => {
- launchOverlay(LazyDeleteHPAModalOverlay, {
+ launchModal(LazyDeleteHPAModalOverlay, {
workload: resource,
hpa: relatedHPAs[0],
});
From eeb71b8f7b35aad48c9707a236d798e41d0e0fe3 Mon Sep 17 00:00:00 2001
From: Steve Goodwin
Date: Thu, 26 Feb 2026 10:48:50 -0500
Subject: [PATCH 9/9] Fix lint issues
---
.../console-shared/src/components/hpa/DeleteHPAModal.tsx | 2 +-
.../src/components/modals/ConsolePluginModal.tsx | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx b/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx
index 6d2fb3bf66..8f26b444ee 100644
--- a/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx
+++ b/frontend/packages/console-shared/src/components/hpa/DeleteHPAModal.tsx
@@ -4,8 +4,8 @@ import { Form } from '@patternfly/react-core';
import { ExclamationTriangleIcon } from '@patternfly/react-icons/dist/esm/icons/exclamation-triangle-icon';
import { t_global_icon_color_status_warning_default as warningColor } from '@patternfly/react-tokens';
import { useTranslation } from 'react-i18next';
+import type { OverlayComponent } from '@console/dynamic-plugin-sdk/src/app/modal-support/OverlayProvider';
import type { ModalComponentProps } from '@console/internal/components/factory/modal';
-import { OverlayComponent } from '@console/dynamic-plugin-sdk/src/app/modal-support/OverlayProvider';
import {
ModalBody,
ModalSubmitFooter,
diff --git a/frontend/packages/console-shared/src/components/modals/ConsolePluginModal.tsx b/frontend/packages/console-shared/src/components/modals/ConsolePluginModal.tsx
index 8d68615159..c38aa4cde9 100644
--- a/frontend/packages/console-shared/src/components/modals/ConsolePluginModal.tsx
+++ b/frontend/packages/console-shared/src/components/modals/ConsolePluginModal.tsx
@@ -1,12 +1,12 @@
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
-import { OverlayComponent } from '@console/dynamic-plugin-sdk/src/app/modal-support/OverlayProvider';
+import type { OverlayComponent } from '@console/dynamic-plugin-sdk/src/app/modal-support/OverlayProvider';
+import type { ModalComponentProps } from '@console/internal/components/factory/modal';
import {
ModalTitle,
ModalBody,
ModalSubmitFooter,
ModalWrapper,
- ModalComponentProps,
} from '@console/internal/components/factory/modal';
import { ConsoleOperatorConfigModel } from '@console/internal/models';
import type { K8sResourceKind } from '@console/internal/module/k8s';