Uploaded image for project: 'OpenShift Console'
  1. OpenShift Console
  2. CONSOLE-4447

Migrate existing custom modal instances to PatternFly ones

XMLWordPrintable

    • Icon: Story Story
    • Resolution: Unresolved
    • Icon: Undefined Undefined
    • None
    • None
    • None
    • None
    • None
    • OCP Console - Sprint 284

      https://github.com/openshift/console/blob/master/frontend/public/components/factory/modal.tsx is a custom modal that pre-dates PatternFly and is used extensively throughout the code base.  We have deferred migrating the instances that use this custom modal due to the amount of work involved.  However, we need to work to remove these instances so we can simplify our implementations, which will make PatternFly upgrades easier.

      # Files Using Deprecated Modal Components
      
      This document lists all files that use the deprecated modal components from `@console/internal/components/factory/modal`:
      
      - `ModalWrapper`
      - `ModalTitle`
      - `ModalBody` (from factory/modal - not the PatternFly ModalBody)
      - `ModalFooter` (from factory/modal - not the PatternFly ModalFooter)
      - `ModalSubmitFooter`
      
      These components should be migrated to use modern PatternFly v6 Modal components (`Modal`, `ModalHeader`, `ModalBody`, `ModalFooter`, etc.) from `@patternfly/react-core`.
      
      ~~Additionally, `packages/console-shared/src/components/modal/Modal.tsx` is a wrapper around the deprecated PatternFly Modal from `@patternfly/react-core/deprecated` and should eventually be removed once all usages are migrated.~~ **REMOVED** - All usages migrated.
      
      ## Migration Status
      
      ### ✅ Already Migrated (9 files)
      
      **From deprecated factory/modal:**
      
      - `public/components/modals/configure-count-modal.tsx` - Uses ModalErrorContent
      - `public/components/modals/configure-machine-autoscaler-modal.tsx` - Uses ModalErrorContent
      - `public/components/modals/delete-modal.tsx` - Uses ModalErrorContent
      - `packages/console-app/src/components/modals/add-group-users-modal.tsx` - Uses modern Modal, fixed button order
      
      **From deprecated Modal wrapper:**
      
      - `packages/console-shared/src/hooks/useCopyCodeModal.tsx` - Migrated to modern PatternFly Modal
      - `packages/console-app/src/components/favorite/FavoriteButton.tsx` - Migrated to modern PatternFly Modal
      - `packages/console-app/src/components/tour/TourStepComponent.tsx` - Migrated to modern PatternFly Modal
      
      **From deprecated PatternFly Modal:**
      
      - `packages/console-shared/src/components/catalog/details/CatalogDetailsModal.tsx` - Migrated to modern Modal
      - `packages/operator-lifecycle-manager/src/components/operator-hub/operator-hub-items.tsx` - Migrated to modern Modal
      
      ### ✅ Already Using Modern PatternFly - Button Variants Updated (10 files)
      
      These files were already using modern PatternFly Modal components but had Cancel buttons with `variant="secondary"` instead of the correct `variant="link"`. They have been updated to follow PatternFly standards:
      
      - `public/components/modals/delete-namespace-modal.tsx`
      - `public/components/secrets/create-secret/SecretFormWrapper.tsx`
      - `packages/console-app/src/components/modals/add-group-users-modal.tsx` - Also fixed button order (Primary first, Cancel second)
      - `packages/console-shared/src/components/modals/CreateNamespaceModal.tsx`
      - `packages/console-shared/src/components/modals/CreateProjectModal.tsx`
      - `packages/metal3-plugin/src/components/modals/PowerOffHostModal.tsx`
      - `packages/metal3-plugin/src/components/modals/RestartHostModal.tsx`
      - `packages/metal3-plugin/src/components/modals/StartNodeMaintenanceModal.tsx`
      - `packages/knative-plugin/src/components/test-function/TestFunctionModal.tsx`
      - `packages/operator-lifecycle-manager/src/components/registry-poll-interval-details.tsx`
      
      **Note:** Some of these files still use the deprecated Modal from `@patternfly/react-core/deprecated` (see below), but the button variant updates are complete.
      
      **Note:** The deprecated Modal wrapper (`packages/console-shared/src/components/modal/`) has been removed as all usages have been migrated.
      
      ### 📋 Files Using Deprecated PatternFly Modal (5 files)
      
      These files use the deprecated Modal component from `@patternfly/react-core/deprecated` instead of the modern Modal from `@patternfly/react-core`. They should be migrated to the modern PatternFly v6 Modal:
      
      **Direct deprecated Modal imports:**
      
      - `packages/console-shared/src/components/modals/CreateNamespaceModal.tsx` - ✅ Button variants updated
      - `packages/console-shared/src/components/modals/CreateProjectModal.tsx` - ✅ Button variants updated
      - `packages/knative-plugin/src/components/test-function/TestFunctionModal.tsx` - ✅ Button variants updated
      - `packages/vsphere-plugin/src/components/VSphereConnectionModal.tsx`
      - `public/components/modals/replace-code-modal.tsx` - Special case: Yes/No/Keep both pattern
      
      **Note:** The deprecated Modal wrapper (`packages/console-shared/src/components/modal/`) has been **REMOVED** - all usages migrated.
      
      ### 📋 Files Using Deprecated useModal Hook (10 files)
      
      These files use the deprecated `useModal` hook from `@console/dynamic-plugin-sdk`. They should be migrated to use the modern `useOverlay` hook instead:
      
      **Hook usage files:**
      
      - `packages/console-shared/src/hooks/useAnnotationsModal.tsx`
      - `packages/console-shared/src/hooks/useCopyCodeModal.tsx` - ✅ Modal migrated to modern PatternFly, but still uses useModal
      - `packages/console-shared/src/hooks/useDeleteModal.tsx`
      - `packages/console-shared/src/hooks/useLabelsModal.tsx`
      - `packages/console-shared/src/hooks/useCreateNamespaceModal.ts`
      - `packages/console-shared/src/hooks/useCreateNamespaceOrProjectModal.ts`
      - `packages/console-shared/src/hooks/useCreateProjectModal.ts`
      - `packages/console-shared/src/components/dashboard/status-card/AlertItem.tsx`
      - `packages/console-app/src/components/oauth-config/IdentityProviders.tsx`
      - `public/components/notification-drawer.tsx`
      
      **Migration:** Replace `useModal` with `useOverlay` from `@console/dynamic-plugin-sdk`. The API is similar, but `useOverlay` is the modern replacement.
      
      ---
      
      ## 📋 Files Requiring Migration
      
      ### Core Console Modals (18 files)
      
      - `public/components/modals/add-secret-to-workload.tsx`
      - `public/components/modals/add-users-modal.tsx`
      - `public/components/modals/alert-routing-modal.tsx`
      - `public/components/modals/cluster-channel-modal.tsx`
      - `public/components/modals/cluster-more-updates-modal.tsx`
      - `public/components/modals/cluster-update-modal.tsx`
      - `public/components/modals/configure-cluster-upstream-modal.tsx`
      - `public/components/modals/configure-ns-pull-secret-modal.tsx`
      - `public/components/modals/configure-update-strategy-modal.tsx`
      - `public/components/modals/confirm-modal.tsx`
      - `public/components/modals/delete-namespace-modal.tsx`
      - `public/components/modals/error-modal.tsx`
      - `public/components/modals/expand-pvc-modal.tsx`
      - `public/components/modals/labels-modal.tsx`
      - `public/components/modals/managed-resource-save-modal.tsx`
      - `public/components/modals/remove-idp-modal.tsx`
      - `public/components/modals/remove-volume-modal.tsx`
      - `public/components/modals/tags.tsx`
      
      ### Console App Package (7 files)
      
      - `packages/console-app/src/components/modals/clone/clone-pvc-modal.tsx`
      - `packages/console-app/src/components/modals/modify-vac-modal.tsx`
      - `packages/console-app/src/components/modals/resource-limits/ResourceLimitsModal.tsx`
      - `packages/console-app/src/components/modals/resource-limits/ResourceLimitsModalLauncher.tsx`
      - `packages/console-app/src/components/modals/restore-pvc/restore-pvc-modal.tsx`
      - `packages/console-app/src/components/nodes/modals/ConfigureUnschedulableModal.tsx`
      - `packages/console-app/src/components/pdb/modals/DeletePDBModal.tsx`
      
      ### Console Shared Package (7 files)
      
      **Deprecated factory/modal usage:**
      
      - `packages/console-shared/src/components/hpa/DeleteHPAModal.tsx`
      - `packages/console-shared/src/components/modals/ConsolePluginModal.tsx`
      - `packages/console-shared/src/components/modals/DeleteResourceModal.tsx`
      - `packages/console-shared/src/hooks/useAnnotationsModal.tsx`
      - `packages/console-shared/src/hooks/useDeleteModal.tsx`
      - `packages/console-shared/src/hooks/useLabelsModal.tsx`
      
      **Deprecated PatternFly Modal wrapper:**
      
      - ~~`packages/console-shared/src/components/modal/Modal.tsx` - Wraps `@patternfly/react-core/deprecated` Modal~~ **REMOVED** - All usages migrated
      
      ### Operator Lifecycle Manager Package (8 files)
      
      - `packages/operator-lifecycle-manager/src/components/modals/delete-catalog-source-modal.tsx`
      - `packages/operator-lifecycle-manager/src/components/modals/disable-default-source-modal.tsx`
      - `packages/operator-lifecycle-manager/src/components/modals/edit-default-sources-modal.tsx`
      - `packages/operator-lifecycle-manager/src/components/modals/installplan-approval-modal.tsx`
      - `packages/operator-lifecycle-manager/src/components/modals/installplan-preview-modal.tsx`
      - `packages/operator-lifecycle-manager/src/components/modals/subscription-channel-modal.tsx`
      - `packages/operator-lifecycle-manager/src/components/modals/uninstall-operator-modal.tsx`
      - `packages/operator-lifecycle-manager/src/components/modals/update-strategy-modal.tsx`
      - `packages/operator-lifecycle-manager/src/components/operator-hub/operator-hub-community-provider-modal.tsx`
      
      **Note:** `packages/operator-lifecycle-manager/src/components/operator-hub/operator-hub-items.tsx` was migrated from deprecated PatternFly Modal (see ✅ Already Migrated section).
      
      ### Topology Package (3 files)
      
      - `packages/topology/src/components/export-app/ExportApplicationModal.tsx`
      - `packages/topology/src/components/modals/EditApplicationModal.tsx`
      - `packages/topology/src/components/modals/MoveConnectionModal.tsx`
      
      ### Helm Plugin (1 file)
      
      - `packages/helm-plugin/src/components/forms/install-upgrade/HelmReadmeModal.tsx`
      
      ### Metal3 Plugin (3 files)
      
      - `packages/metal3-plugin/src/components/modals/PowerOffHostModal.tsx`
      - `packages/metal3-plugin/src/components/modals/RestartHostModal.tsx`
      - `packages/metal3-plugin/src/components/modals/StartNodeMaintenanceModal.tsx`
      
      ### Knative Plugin (15 files)
      
      - `packages/knative-plugin/src/components/pub-sub/PubSubController.tsx`
      - `packages/knative-plugin/src/components/pub-sub/PubSubModal.tsx`
      - `packages/knative-plugin/src/components/revisions/DeleteRevisionModal.tsx`
      - `packages/knative-plugin/src/components/revisions/DeleteRevisionModalController.tsx`
      - `packages/knative-plugin/src/components/sink-pubsub/SinkPubsubController.tsx`
      - `packages/knative-plugin/src/components/sink-pubsub/SinkPubsubModal.tsx`
      - `packages/knative-plugin/src/components/sink-source/SinkSourceController.tsx`
      - `packages/knative-plugin/src/components/sink-source/SinkSourceModal.tsx`
      - `packages/knative-plugin/src/components/sink-uri/SinkUriController.tsx`
      - `packages/knative-plugin/src/components/sink-uri/SinkUriModal.tsx`
      - `packages/knative-plugin/src/components/test-function/TestFunctionController.tsx`
      - `packages/knative-plugin/src/components/test-function/TestFunctionModal.tsx`
      - `packages/knative-plugin/src/components/traffic-splitting/TrafficSplittingController.tsx`
      - `packages/knative-plugin/src/components/traffic-splitting/TrafficSplittingModal.tsx`
      
      ---
      
      ## Summary
      
      - **Total files using deprecated factory/modal:** 62
      - **Deprecated PatternFly Modal wrappers:** ~~1~~ **0** (wrapper removed - all usages migrated)
      - **Already migrated:** 9 (4 from factory/modal + 3 from deprecated wrapper + 2 from deprecated PatternFly Modal)
      - **Button variants updated:** 10 modern PatternFly modals
      - **Remaining:** 56 (54 factory/modal + 2 deprecated PatternFly Modal that still need full migration)
      - **Files using deprecated useModal hook:** 10 files (should migrate to useOverlay)
      - **Files using deprecated PatternFly Modal:** 5 files (should migrate to modern Modal)
      
      **Note:** 7 files still use deprecated PatternFly Modal but only need button variant updates (3 already completed, 4 still use deprecated Modal imports - see sections above).
      
      **Breakdown by package:**
      
      - Core Console Modals: 18 files
      - Console App: 7 files (was 8, migrated add-group-users-modal)
      - Console Shared: 6 files (was 7, removed deprecated Modal wrapper)
      - Operator Lifecycle Manager: 8 files
      - Topology: 3 files
      - Knative Plugin: 15 files
      - Helm Plugin: 1 file
      - Metal3 Plugin: 3 files
      
      ## Migration Pattern
      
      The standard migration pattern from deprecated components to modern PatternFly v6:
      
      ### Before (Deprecated):
      
      ```tsx
      import {
        createModalLauncher,
        ModalWrapper,
        ModalTitle,
        ModalBody,
        ModalSubmitFooter,
      } from '@console/internal/components/factory/modal';
      
      <ModalWrapper>
        <ModalTitle>Delete Resource?</ModalTitle>
        <ModalBody>Are you sure?</ModalBody>
        <ModalSubmitFooter
          errorMessage={errorMessage}
          inProgress={inProgress}
          submitText="Delete"
          cancel={cancel}
        />
      </ModalWrapper>;
      ```
      
      ### After (Modern PatternFly v6):
      
      ```tsx
      import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from '@patternfly/react-core';
      import { ModalErrorContent } from '@console/shared/src/components/modal-error-content';
      
      <Modal isOpen onClose={closeModal} variant={ModalVariant.small}>
        <ModalHeader title="Delete Resource?" />
        <ModalBody>
          Are you sure?
          <ModalErrorContent errorMessage={errorMessage} />
        </ModalBody>
        <ModalFooter>
          <Button variant="danger" onClick={submit} isLoading={inProgress}>
            Delete
          </Button>
          <Button variant="link" onClick={cancel}>
            Cancel
          </Button>
        </ModalFooter>
      </Modal>;
      ```
      
      ## Key Changes
      
      1. **Error handling:** Move from ModalFooter to end of ModalBody using `ModalErrorContent` component
      2. **Button order:** Primary/Danger action button comes **first**, Cancel button comes **second**
         - ✅ Correct: `<Button variant="primary">Submit</Button>` then `<Button variant="link">Cancel</Button>`
         - ❌ Wrong: Cancel button first
      3. **Cancel button variant:** Use `variant="link"` for Cancel buttons (PatternFly standard)
         - ✅ Correct: `<Button variant="link">Cancel</Button>`
         - ❌ Wrong: `<Button variant="secondary">Cancel</Button>`
      4. **Modal structure:** Use ModalHeader instead of ModalTitle
      5. **Buttons:** Place directly in ModalFooter (no wrapper component)
      6. **Close handler:** Add onClose prop to Modal for X button
      
      ## useModal to useOverlay Migration
      
      The `useModal` hook is deprecated and should be replaced with `useOverlay`:
      
      ### Before (Deprecated useModal)
      
      ```tsx
      import { useModal } from '@console/dynamic-plugin-sdk/src/app/modal-support/useModal';
      
      const MyComponent = () => {
        const launchModal = useModal();
      
        const onClick = () => {
          launchModal(MyModalComponent, { title: 'My Modal' });
        };
      
        return <Button onClick={onClick}>Open Modal</Button>;
      };
      ```
      
      ### After (Modern useOverlay)
      
      ```tsx
      import { useOverlay } from '@console/dynamic-plugin-sdk';
      
      const MyComponent = () => {
        const launchOverlay = useOverlay();
      
        const onClick = () => {
          launchOverlay(MyModalComponent, { title: 'My Modal' });
        };
      
        return <Button onClick={onClick}>Open Modal</Button>;
      };
      ```
      
      **Key Changes:**
      
      - Import `useOverlay` from `@console/dynamic-plugin-sdk` instead of `useModal`
      - Rename the hook variable from `launchModal` to `launchOverlay` (convention)
      - The API is otherwise identical
      
      ---
      
      Generated: 2026-02-09
      
      
      

              rhn-engineering-rhamilto Robb Hamilton
              rhn-engineering-rhamilto Robb Hamilton
              None
              None
              None
              None
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Created:
                Updated: