diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/ModelManagerModal.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/ModelManagerModal.tsx
deleted file mode 100644
index 126bd402ec..0000000000
--- a/invokeai/frontend/web/src/features/system/components/ModelManager/ModelManagerModal.tsx
+++ /dev/null
@@ -1,93 +0,0 @@
-import {
- Flex,
- Modal,
- ModalBody,
- ModalCloseButton,
- ModalContent,
- ModalFooter,
- ModalHeader,
- ModalOverlay,
- useDisclosure,
-} from '@chakra-ui/react';
-import { cloneElement } from 'react';
-
-import { RootState } from 'app/store/store';
-import { useAppSelector } from 'app/store/storeHooks';
-import { useTranslation } from 'react-i18next';
-
-import type { ReactElement } from 'react';
-
-import { useListModelsQuery } from 'services/api/endpoints/models';
-import CheckpointModelEdit from './CheckpointModelEdit';
-import DiffusersModelEdit from './DiffusersModelEdit';
-import ModelList from './ModelList';
-
-type ModelManagerModalProps = {
- children: ReactElement;
-};
-
-export default function ModelManagerModal({
- children,
-}: ModelManagerModalProps) {
- const {
- isOpen: isModelManagerModalOpen,
- onOpen: onModelManagerModalOpen,
- onClose: onModelManagerModalClose,
- } = useDisclosure();
-
- const { data: pipelineModels } = useListModelsQuery({
- model_type: 'pipeline',
- });
-
- const openModel = useAppSelector(
- (state: RootState) => state.system.openModel
- );
-
- const { t } = useTranslation();
-
- const renderModelEditTabs = () => {
- if (!openModel || !pipelineModels) return;
-
- if (pipelineModels['entities'][openModel]['model_format'] === 'diffusers') {
- return (
-
- );
- } else {
- return (
-
- );
- }
- };
-
- return (
- <>
- {cloneElement(children, {
- onClick: onModelManagerModalOpen,
- })}
-
-
-
-
- {t('modelManager.modelManager')}
-
-
-
- {renderModelEditTabs()}
-
-
-
-
-
- >
- );
-}
diff --git a/invokeai/frontend/web/src/features/system/components/SiteHeader.tsx b/invokeai/frontend/web/src/features/system/components/SiteHeader.tsx
index 0c94c1d2f9..758f03f19a 100644
--- a/invokeai/frontend/web/src/features/system/components/SiteHeader.tsx
+++ b/invokeai/frontend/web/src/features/system/components/SiteHeader.tsx
@@ -5,21 +5,18 @@ import StatusIndicator from './StatusIndicator';
import { Link } from '@chakra-ui/react';
import IAIIconButton from 'common/components/IAIIconButton';
import { useTranslation } from 'react-i18next';
-import { FaBug, FaCube, FaDiscord, FaGithub, FaKeyboard } from 'react-icons/fa';
+import { FaBug, FaDiscord, FaGithub, FaKeyboard } from 'react-icons/fa';
import { MdSettings } from 'react-icons/md';
+import { useFeatureStatus } from '../hooks/useFeatureStatus';
+import ColorModeButton from './ColorModeButton';
import HotkeysModal from './HotkeysModal/HotkeysModal';
import InvokeAILogoComponent from './InvokeAILogoComponent';
import LanguagePicker from './LanguagePicker';
-import ModelManagerModal from './ModelManager/ModelManagerModal';
import SettingsModal from './SettingsModal/SettingsModal';
-import { useFeatureStatus } from '../hooks/useFeatureStatus';
-import ColorModeButton from './ColorModeButton';
const SiteHeader = () => {
const { t } = useTranslation();
- const isModelManagerEnabled =
- useFeatureStatus('modelManager').isFeatureEnabled;
const isLocalizationEnabled =
useFeatureStatus('localization').isFeatureEnabled;
const isBugLinkEnabled = useFeatureStatus('bugLink').isFeatureEnabled;
@@ -37,20 +34,6 @@ const SiteHeader = () => {
- {isModelManagerEnabled && (
-
- }
- />
-
- )}
-
,
+ },
+ {
+ id: 'add_models',
+ label: i18n.t('modelManager.addModel'),
+ content: ,
+ },
+ {
+ id: 'merge_models',
+ label: i18n.t('modelManager.mergeModels'),
+ content: ,
+ },
+];
const ModelManagerTab = () => {
- return 'Model Manager';
+ const renderTabsList = () => {
+ const modelManagerTabListsToRender: ReactNode[] = [];
+ modelManagerTabs.forEach((modelManagerTab) => {
+ modelManagerTabListsToRender.push(
+ {modelManagerTab.label}
+ );
+ });
+
+ return (
+
+ {modelManagerTabListsToRender}
+
+ );
+ };
+
+ const renderTabPanels = () => {
+ const modelManagerTabPanelsToRender: ReactNode[] = [];
+ modelManagerTabs.forEach((modelManagerTab) => {
+ modelManagerTabPanelsToRender.push(
+ {modelManagerTab.content}
+ );
+ });
+
+ return {modelManagerTabPanelsToRender};
+ };
+
+ return (
+
+ {renderTabsList()}
+ {renderTabPanels()}
+
+ );
};
export default memo(ModelManagerTab);
diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel.tsx
new file mode 100644
index 0000000000..b1c03fcb6b
--- /dev/null
+++ b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel.tsx
@@ -0,0 +1,10 @@
+import { Flex } from '@chakra-ui/react';
+import AddModel from 'features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/AddModel';
+
+export default function AddModelsPanel() {
+ return (
+
+
+
+ );
+}
diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/AddCheckpointModel.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/AddCheckpointModel.tsx
similarity index 99%
rename from invokeai/frontend/web/src/features/system/components/ModelManager/AddCheckpointModel.tsx
rename to invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/AddCheckpointModel.tsx
index e6bd0b6ffb..75e2017bb8 100644
--- a/invokeai/frontend/web/src/features/system/components/ModelManager/AddCheckpointModel.tsx
+++ b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/AddCheckpointModel.tsx
@@ -10,13 +10,11 @@ import {
} from '@chakra-ui/react';
import IAIButton from 'common/components/IAIButton';
-import IAISimpleCheckbox from 'common/components/IAISimpleCheckbox';
import IAIInput from 'common/components/IAIInput';
import IAINumberInput from 'common/components/IAINumberInput';
+import IAISimpleCheckbox from 'common/components/IAISimpleCheckbox';
import React from 'react';
-import SearchModels from './SearchModels';
-
// import { addNewModel } from 'app/socketio/actions';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
@@ -24,12 +22,13 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { Field, Formik } from 'formik';
import { useTranslation } from 'react-i18next';
-import type { InvokeModelConfigProps } from 'app/types/invokeai';
import type { RootState } from 'app/store/store';
-import { setAddNewModelUIOption } from 'features/ui/store/uiSlice';
-import type { FieldInputProps, FormikProps } from 'formik';
+import type { InvokeModelConfigProps } from 'app/types/invokeai';
import IAIForm from 'common/components/IAIForm';
import { IAIFormItemWrapper } from 'common/components/IAIForms/IAIFormItemWrapper';
+import { setAddNewModelUIOption } from 'features/ui/store/uiSlice';
+import type { FieldInputProps, FormikProps } from 'formik';
+import SearchModels from './SearchModels';
const MIN_MODEL_SIZE = 64;
const MAX_MODEL_SIZE = 2048;
diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/AddDiffusersModel.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/AddDiffusersModel.tsx
similarity index 100%
rename from invokeai/frontend/web/src/features/system/components/ModelManager/AddDiffusersModel.tsx
rename to invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/AddDiffusersModel.tsx
diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/AddModel.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/AddModel.tsx
similarity index 100%
rename from invokeai/frontend/web/src/features/system/components/ModelManager/AddModel.tsx
rename to invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/AddModel.tsx
diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/SearchModels.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/SearchModels.tsx
similarity index 100%
rename from invokeai/frontend/web/src/features/system/components/ModelManager/SearchModels.tsx
rename to invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/SearchModels.tsx
diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/MergeModelsPanel.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/MergeModelsPanel.tsx
new file mode 100644
index 0000000000..8c26357720
--- /dev/null
+++ b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/MergeModelsPanel.tsx
@@ -0,0 +1,10 @@
+import { Flex } from '@chakra-ui/react';
+import MergeModels from 'features/ui/components/tabs/ModelManager/subpanels/MergeModelsPanel/MergeModels';
+
+export default function MergeModelsPanel() {
+ return (
+
+
+
+ );
+}
diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/MergeModels.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/MergeModelsPanel/MergeModels.tsx
similarity index 100%
rename from invokeai/frontend/web/src/features/system/components/ModelManager/MergeModels.tsx
rename to invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/MergeModelsPanel/MergeModels.tsx
diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel.tsx
new file mode 100644
index 0000000000..d3c4085e90
--- /dev/null
+++ b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel.tsx
@@ -0,0 +1,44 @@
+import { Flex } from '@chakra-ui/react';
+import { RootState } from 'app/store/store';
+import { useAppSelector } from 'app/store/storeHooks';
+
+import { useListModelsQuery } from 'services/api/endpoints/models';
+import CheckpointModelEdit from './ModelManagerPanel/CheckpointModelEdit';
+import DiffusersModelEdit from './ModelManagerPanel/DiffusersModelEdit';
+import ModelList from './ModelManagerPanel/ModelList';
+
+export default function ModelManagerPanel() {
+ const { data: pipelineModels } = useListModelsQuery({
+ model_type: 'pipeline',
+ });
+
+ const openModel = useAppSelector(
+ (state: RootState) => state.system.openModel
+ );
+
+ const renderModelEditTabs = () => {
+ if (!openModel || !pipelineModels) return;
+
+ if (pipelineModels['entities'][openModel]['model_format'] === 'diffusers') {
+ return (
+
+ );
+ } else {
+ return (
+
+ );
+ }
+ };
+ return (
+
+
+ {renderModelEditTabs()}
+
+ );
+}
diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/CheckpointModelEdit.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/CheckpointModelEdit.tsx
similarity index 100%
rename from invokeai/frontend/web/src/features/system/components/ModelManager/CheckpointModelEdit.tsx
rename to invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/CheckpointModelEdit.tsx
diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/DiffusersModelEdit.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/DiffusersModelEdit.tsx
similarity index 100%
rename from invokeai/frontend/web/src/features/system/components/ModelManager/DiffusersModelEdit.tsx
rename to invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/DiffusersModelEdit.tsx
diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/ModelConvert.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/ModelConvert.tsx
similarity index 100%
rename from invokeai/frontend/web/src/features/system/components/ModelManager/ModelConvert.tsx
rename to invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/ModelConvert.tsx
diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/ModelList.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/ModelList.tsx
similarity index 94%
rename from invokeai/frontend/web/src/features/system/components/ModelManager/ModelList.tsx
rename to invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/ModelList.tsx
index b090c2a07b..3099a18325 100644
--- a/invokeai/frontend/web/src/features/system/components/ModelManager/ModelList.tsx
+++ b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/ModelList.tsx
@@ -1,9 +1,7 @@
-import { Box, Flex, Heading, Spacer, Spinner, Text } from '@chakra-ui/react';
+import { Box, Flex, Spinner, Text } from '@chakra-ui/react';
import IAIButton from 'common/components/IAIButton';
import IAIInput from 'common/components/IAIInput';
-import AddModel from './AddModel';
-import MergeModels from './MergeModels';
import ModelListItem from './ModelListItem';
import { useTranslation } from 'react-i18next';
@@ -185,13 +183,6 @@ const ModelList = () => {
return (
-
- {t('modelManager.availableModels')}
-
-
-
-
-