diff --git a/ui/components/app/modals/modal.js b/ui/components/app/modals/modal.js
index f3eb1a950a40..4f488701bad5 100644
--- a/ui/components/app/modals/modal.js
+++ b/ui/components/app/modals/modal.js
@@ -117,7 +117,7 @@ const custodyConfirmModalStyle = {
const MODALS = {
ONBOARDING_ADD_NETWORK: {
- contents: ,
+ contents: ,
testId: 'add-network-modal',
...accountModalStyle,
},
diff --git a/ui/components/multichain/network-list-menu/network-list-menu.js b/ui/components/multichain/network-list-menu/network-list-menu.js
index 022ad7f055b0..6f1c6dab3233 100644
--- a/ui/components/multichain/network-list-menu/network-list-menu.js
+++ b/ui/components/multichain/network-list-menu/network-list-menu.js
@@ -67,12 +67,23 @@ import {
getIsUnlocked,
} from '../../../ducks/metamask/metamask';
import { getLocalNetworkMenuRedesignFeatureFlag } from '../../../helpers/utils/feature-flags';
+import AddNetworkModal from '../../../pages/onboarding-flow/add-network-modal';
import PopularNetworkList from './popular-network-list/popular-network-list';
import NetworkListSearch from './network-list-search/network-list-search';
+const ACTION_MODES = {
+ // Displays the search box and network list
+ LIST: 'list',
+ // Displays the Add form
+ ADD: 'add',
+ // Displays the Edit form
+ EDIT: 'edit',
+};
+
export const NetworkListMenu = ({ onClose }) => {
const t = useI18nContext();
+ const [actionMode, setActionMode] = useState(ACTION_MODES.LIST);
const nonTestNetworks = useSelector(getNonTestNetworks);
const testNetworks = useSelector(getTestNetworks);
const showTestNetworks = useSelector(getShowTestNetworks);
@@ -99,6 +110,13 @@ export const NetworkListMenu = ({ onClose }) => {
const isUnlocked = useSelector(getIsUnlocked);
+ let title = t('networkMenuHeading');
+ if (actionMode === ACTION_MODES.ADD) {
+ title = t('addCustomNetwork');
+ } else if (actionMode === ACTION_MODES.EDIT) {
+ title = currentNetwork.nickname;
+ }
+
const orderedNetworksList = useSelector(getOrderedNetworksList);
const networkConfigurationChainIds = Object.values(networkConfigurations).map(
@@ -315,6 +333,11 @@ export const NetworkListMenu = ({ onClose }) => {
}
};
+ const headerAdditionalProps =
+ actionMode === ACTION_MODES.LIST
+ ? {}
+ : { onBack: () => setActionMode(ACTION_MODES.LIST) };
+
return (
@@ -332,145 +355,156 @@ export const NetworkListMenu = ({ onClose }) => {
paddingRight={4}
paddingBottom={6}
onClose={onClose}
+ {...headerAdditionalProps}
>
- {t('networkMenuHeading')}
+ {title}
- <>
-
- {showBanner ? (
-
-
-
- }
- onClose={() => hideNetworkBanner()}
- description={t('dragAndDropBanner')}
+ {actionMode === ACTION_MODES.LIST ? (
+ <>
+
- ) : null}
-
- {searchResults.length === 0 && focusSearch ? (
-
- {t('noNetworksFound')}
-
- ) : (
-
-
- {(provided) => (
-
- {searchResults.map((network, index) => {
- const isCurrentNetwork =
- currentNetwork.id === network.id;
-
- const canDeleteNetwork =
- isUnlocked && !isCurrentNetwork && network.removable;
-
- const networkListItem = generateNetworkListItem({
- network,
- isCurrentNetwork,
- canDeleteNetwork,
- });
-
- return (
-
- {(providedDrag) => (
-
- {networkListItem}
-
- )}
-
- );
- })}
- {provided.placeholder}
-
- )}
-
-
- )}
- {networkMenuRedesign ? (
-
+
+
+ }
+ onClose={() => hideNetworkBanner()}
+ description={t('dragAndDropBanner')}
/>
) : null}
-
- {t('showTestnetNetworks')}
-
-
- {showTestNetworks || currentlyOnTestNetwork ? (
-
- {generateMenuItems(searchTestNetworkResults)}
+
+ {searchResults.length === 0 && focusSearch ? (
+
+ {t('noNetworksFound')}
+
+ ) : (
+
+
+ {(provided) => (
+
+ {searchResults.map((network, index) => {
+ const isCurrentNetwork =
+ currentNetwork.id === network.id;
+
+ const canDeleteNetwork =
+ isUnlocked &&
+ !isCurrentNetwork &&
+ network.removable;
+
+ const networkListItem = generateNetworkListItem({
+ network,
+ isCurrentNetwork,
+ canDeleteNetwork,
+ });
+
+ return (
+
+ {(providedDrag) => (
+
+ {networkListItem}
+
+ )}
+
+ );
+ })}
+ {provided.placeholder}
+
+ )}
+
+
+ )}
+ {networkMenuRedesign ? (
+
+ ) : null}
+
+ {t('showTestnetNetworks')}
+
- ) : null}
-
-
- {
- if (isFullScreen) {
- if (completedOnboarding) {
- history.push(ADD_POPULAR_CUSTOM_NETWORK);
- } else {
- dispatch(showModal({ name: 'ONBOARDING_ADD_NETWORK' }));
+ {showTestNetworks || currentlyOnTestNetwork ? (
+
+ {generateMenuItems(searchTestNetworkResults)}
+
+ ) : null}
+
+
+ {
+ if (!networkMenuRedesign) {
+ if (isFullScreen) {
+ if (completedOnboarding) {
+ history.push(ADD_POPULAR_CUSTOM_NETWORK);
+ } else {
+ dispatch(showModal({ name: 'ONBOARDING_ADD_NETWORK' }));
+ }
+ } else {
+ global.platform.openExtensionInBrowser(
+ ADD_POPULAR_CUSTOM_NETWORK,
+ );
+ }
+ dispatch(toggleNetworkMenu());
+ return;
}
- } else {
- global.platform.openExtensionInBrowser(
- ADD_POPULAR_CUSTOM_NETWORK,
- );
- }
- dispatch(toggleNetworkMenu());
- trackEvent({
- event: MetaMetricsEventName.AddNetworkButtonClick,
- category: MetaMetricsEventCategory.Network,
- });
- }}
- >
- {t('addNetwork')}
-
-
- >
+ trackEvent({
+ event: MetaMetricsEventName.AddNetworkButtonClick,
+ category: MetaMetricsEventCategory.Network,
+ });
+ setActionMode(ACTION_MODES.ADD);
+ }}
+ >
+ {t('addNetwork')}
+
+
+ >
+ ) : (
+
+ )}
);
diff --git a/ui/pages/onboarding-flow/add-network-modal/add-network-modal.test.js b/ui/pages/onboarding-flow/add-network-modal/add-network-modal.test.js
index 69f0570a0252..5a098ceed47e 100644
--- a/ui/pages/onboarding-flow/add-network-modal/add-network-modal.test.js
+++ b/ui/pages/onboarding-flow/add-network-modal/add-network-modal.test.js
@@ -12,12 +12,25 @@ jest.mock('../../../store/actions', () => ({
}));
describe('Add Network Modal', () => {
+ // Set the environment variable before tests run
+ beforeEach(() => {
+ process.env.ENABLE_NETWORK_UI_REDESIGN = '';
+ });
+
+ // Reset the environment variable after tests complete
+ afterEach(() => {
+ delete process.env.ENABLE_NETWORK_UI_REDESIGN;
+ });
+
it('should render', async () => {
const mockStore = configureMockStore([])({
metamask: { useSafeChainsListValidation: true },
});
- const { container } = renderWithProvider(, mockStore);
+ const { container } = renderWithProvider(
+ ,
+ mockStore,
+ );
await waitFor(() => {
expect(container).toMatchSnapshot();
@@ -29,7 +42,10 @@ describe('Add Network Modal', () => {
metamask: { useSafeChainsListValidation: true },
});
- const { queryByText } = renderWithProvider(, mockStore);
+ const { queryByText } = renderWithProvider(
+ ,
+ mockStore,
+ );
const cancelButton = queryByText('Cancel');
fireEvent.click(cancelButton);
@@ -38,4 +54,20 @@ describe('Add Network Modal', () => {
expect(mockHideModal).toHaveBeenCalledTimes(1);
});
});
+
+ it('should not render the new network flow modal', async () => {
+ const mockStore = configureMockStore([thunk])({
+ metamask: { useSafeChainsListValidation: true },
+ });
+
+ const { queryByText } = renderWithProvider(
+ ,
+ mockStore,
+ );
+
+ await waitFor(() => {
+ expect(queryByText('Cancel')).not.toBeInTheDocument();
+ expect(queryByText('Save')).toBeInTheDocument();
+ });
+ });
});
diff --git a/ui/pages/onboarding-flow/add-network-modal/index.js b/ui/pages/onboarding-flow/add-network-modal/index.js
index e3f813d04054..2f2b820d9791 100644
--- a/ui/pages/onboarding-flow/add-network-modal/index.js
+++ b/ui/pages/onboarding-flow/add-network-modal/index.js
@@ -1,5 +1,6 @@
import React from 'react';
import { useDispatch } from 'react-redux';
+import PropTypes from 'prop-types';
import { useI18nContext } from '../../../hooks/useI18nContext';
import { hideModal } from '../../../store/actions';
@@ -14,7 +15,9 @@ import {
import NetworksForm from '../../settings/networks-tab/networks-form/networks-form';
-export default function AddNetworkModal() {
+export default function AddNetworkModal({
+ newNetworkMenuDesignActive = false,
+}) {
const dispatch = useDispatch();
const t = useI18nContext();
@@ -23,15 +26,17 @@ export default function AddNetworkModal() {
return (
<>
-
-
- {t('onboardingMetametricsModalTitle')}
-
-
+ {newNetworkMenuDesignActive ? null : (
+
+
+ {t('onboardingMetametricsModalTitle')}
+
+
+ )}
>
);
}
+
+AddNetworkModal.propTypes = {
+ newNetworkMenuDesignActive: PropTypes.bool,
+};
+
+AddNetworkModal.defaultProps = {
+ newNetworkMenuDesignActive: false,
+};
diff --git a/ui/pages/settings/networks-tab/index.scss b/ui/pages/settings/networks-tab/index.scss
index b8d1458a77ed..bbe958c3c6e0 100644
--- a/ui/pages/settings/networks-tab/index.scss
+++ b/ui/pages/settings/networks-tab/index.scss
@@ -220,8 +220,14 @@
}
}
+ &__new-network-form-footer {
+ position: sticky;
+ bottom: 0;
+ }
+
&__add-network-form {
- padding: 16px 24px;
+ margin-left: 16px;
+ margin-right: 16px;
grid-column: span 2; // spread both columns of grid layout
@include design-system.screen-sm-min {
diff --git a/ui/pages/settings/networks-tab/networks-form/networks-form.js b/ui/pages/settings/networks-tab/networks-form/networks-form.js
index b5a072ac3312..7b9e87097c5e 100644
--- a/ui/pages/settings/networks-tab/networks-form/networks-form.js
+++ b/ui/pages/settings/networks-tab/networks-form/networks-form.js
@@ -44,17 +44,25 @@ import {
setSelectedNetworkConfigurationId,
showDeprecatedNetworkModal,
showModal,
+ toggleNetworkMenu,
upsertNetworkConfiguration,
} from '../../../../store/actions';
import {
+ Box,
ButtonLink,
+ ButtonPrimary,
+ ButtonPrimarySize,
HelpText,
HelpTextSeverity,
Text,
} from '../../../../components/component-library';
import { FormTextField } from '../../../../components/component-library/form-text-field/deprecated';
import {
+ AlignItems,
+ BackgroundColor,
+ BlockSize,
FontWeight,
+ TextAlign,
TextColor,
TextVariant,
} from '../../../../helpers/constants/design-system';
@@ -104,6 +112,7 @@ const NetworksForm = ({
selectedNetwork,
cancelCallback,
submitCallback,
+ newNetworkMenuDesignActive,
}) => {
const t = useI18nContext();
const dispatch = useDispatch();
@@ -860,36 +869,61 @@ const NetworksForm = ({
dataTestId="network-form-block-explorer-url"
/>
-
- {!viewOnly && (
- <>
- {deletable && (
-
+ )}
);
};
@@ -903,10 +937,12 @@ NetworksForm.propTypes = {
submitCallback: PropTypes.func,
restrictHeight: PropTypes.bool,
setActiveOnSubmit: PropTypes.bool,
+ newNetworkMenuDesignActive: PropTypes.bool,
};
NetworksForm.defaultProps = {
selectedNetwork: {},
+ newNetworkMenuDesignActive: false,
};
export default NetworksForm;