diff --git a/src/app/atoms/FormField.tsx b/src/app/atoms/FormField.tsx index c18f25dde8..bf51934942 100644 --- a/src/app/atoms/FormField.tsx +++ b/src/app/atoms/FormField.tsx @@ -43,6 +43,7 @@ export interface FormFieldProps extends TestIDProperty, Omit( labelWarning, errorCaption, shouldShowErrorCaption = true, + reserveSpaceForError = true, warning = false, containerClassName, labelContainerClassName, @@ -257,7 +259,12 @@ export const FormField = forwardRef( {secretCovered && } - {shouldShowErrorCaption && } + {shouldShowErrorCaption && + (reserveSpaceForError && !errorCaption ? ( +
+ ) : ( + + ))}
); } diff --git a/src/app/atoms/PageModal/actions-buttons-box.tsx b/src/app/atoms/PageModal/actions-buttons-box.tsx index bcf5ae4705..3bffb75ac1 100644 --- a/src/app/atoms/PageModal/actions-buttons-box.tsx +++ b/src/app/atoms/PageModal/actions-buttons-box.tsx @@ -17,7 +17,7 @@ export const ActionsButtonsBox = memo( const dispatch = useDispatch(); useEffect(() => { - return () => void shouldChangeBottomShift && dispatch(setToastsContainerBottomShiftAction(0)); + return () => void (shouldChangeBottomShift && dispatch(setToastsContainerBottomShiftAction(0))); }, [dispatch, shouldChangeBottomShift]); const handleResize = useMemo( diff --git a/src/app/layouts/PageLayout/BackupMnemonicOverlay/index.tsx b/src/app/layouts/PageLayout/BackupMnemonicOverlay/index.tsx index 07f4c70157..f179681949 100644 --- a/src/app/layouts/PageLayout/BackupMnemonicOverlay/index.tsx +++ b/src/app/layouts/PageLayout/BackupMnemonicOverlay/index.tsx @@ -1,11 +1,12 @@ -import React, { memo, useCallback, useState } from 'react'; +import React, { memo, useCallback, useContext, useState } from 'react'; import { ManualBackupModal } from 'app/templates/ManualBackupModal'; -import { toastError, toastSuccess } from 'app/toaster'; +import { toastError } from 'app/toaster'; import { SHOULD_BACKUP_MNEMONIC_STORAGE_KEY } from 'lib/constants'; import { t } from 'lib/i18n'; import { useStorage } from 'lib/temple/front'; import { clearMnemonicToBackup, getMnemonicToBackup } from 'lib/temple/front/mnemonic-to-backup-keeper'; +import { SuccessfulInitToastContext } from 'lib/temple/front/successful-init-toast-context'; import { BackupOptionsModal } from './backup-options-modal'; @@ -14,6 +15,7 @@ export const BackupMnemonicOverlay = memo(() => { const [backupSelected, setBackupSelected] = useState(false); const [mnemonicToBackup, setMnemonicToBackup] = useState(''); const [, setShouldBackupMnemonic] = useStorage(SHOULD_BACKUP_MNEMONIC_STORAGE_KEY, false); + const [, setInitToast] = useContext(SuccessfulInitToastContext); const handleBackupOptionSelect = useCallback(async () => { const currentMnemonicToBackup = await getMnemonicToBackup(); @@ -29,10 +31,10 @@ export const BackupMnemonicOverlay = memo(() => { setBackupSelected(false); }, []); const handleSeedPhraseVerified = useCallback(() => { - toastSuccess(t('backupSuccessful')); + setInitToast(t('backupSuccessful')); clearMnemonicToBackup(); setShouldBackupMnemonic(false).catch(e => console.error(e)); - }, [setShouldBackupMnemonic]); + }, [setInitToast, setShouldBackupMnemonic]); return backupSelected ? ( diff --git a/src/app/pages/AccountSettings/edit-account-name-modal.tsx b/src/app/pages/AccountSettings/edit-account-name-modal.tsx index a5561bfb5d..83dbbd55d6 100644 --- a/src/app/pages/AccountSettings/edit-account-name-modal.tsx +++ b/src/app/pages/AccountSettings/edit-account-name-modal.tsx @@ -62,6 +62,7 @@ export const EditAccountNameModal = memo(({ account, name="name" placeholder={account.name} errorCaption={errors.name?.message} + reserveSpaceForError={false} containerClassName="mb-1" testID={AccountSettingsSelectors.accountNameInput} /> diff --git a/src/app/pages/AccountSettings/remove-account-modal.tsx b/src/app/pages/AccountSettings/remove-account-modal.tsx index 0ed9dec20d..671956daa5 100644 --- a/src/app/pages/AccountSettings/remove-account-modal.tsx +++ b/src/app/pages/AccountSettings/remove-account-modal.tsx @@ -84,6 +84,7 @@ export const RemoveAccountModal = memo(({ account, onCl name="password" placeholder={DEFAULT_PASSWORD_INPUT_PLACEHOLDER} errorCaption={errors.password?.message} + reserveSpaceForError={false} containerClassName="mb-1" testID={AccountSettingsSelectors.passwordInput} /> diff --git a/src/app/pages/ChainSettings/manage-url-entities-view/create-modal.tsx b/src/app/pages/ChainSettings/manage-url-entities-view/create-modal.tsx index 0e442544da..4a64d3e468 100644 --- a/src/app/pages/ChainSettings/manage-url-entities-view/create-modal.tsx +++ b/src/app/pages/ChainSettings/manage-url-entities-view/create-modal.tsx @@ -76,7 +76,7 @@ export const CreateUrlEntityModal = memo( const signal = abortAndRenewSignal(); await createEntity(values, signal); closeModal(); - setTimeout(() => toastSuccess(t(successMessageI18nKey)), CLOSE_ANIMATION_TIMEOUT * 2); + setTimeout(() => toastSuccess(t(successMessageI18nKey)), CLOSE_ANIMATION_TIMEOUT + 100); } catch (error) { if (isAbortError(error)) { return; diff --git a/src/app/pages/ChainSettings/manage-url-entities-view/edit-modal.tsx b/src/app/pages/ChainSettings/manage-url-entities-view/edit-modal.tsx index 42808c8438..b5cf92eed6 100644 --- a/src/app/pages/ChainSettings/manage-url-entities-view/edit-modal.tsx +++ b/src/app/pages/ChainSettings/manage-url-entities-view/edit-modal.tsx @@ -121,11 +121,11 @@ export const EditUrlEntityModal = ({ >
- + } Component="div"> (props => { const tabSlug = useLocationSearchParamValue('tab'); const { onboardingCompleted } = useOnboardingProgress(); const { search } = useLocation(); + const dispatch = useDispatch(); - const [shouldShowImportToast, setShouldShowImportToast] = useContext(SuccessfulImportToastContext); + const [initToastMessage, setInitToastMessage] = useContext(SuccessfulInitToastContext); useEffect(() => { - if (shouldShowImportToast) { - setShouldShowImportToast(false); - toastSuccess(t('importSuccessful')); - } - }, [setShouldShowImportToast, shouldShowImportToast]); + if (!initToastMessage) return; + + const timeout = setTimeout(() => { + dispatch(setToastsContainerBottomShiftAction(0)); + setInitToastMessage(undefined); + toastSuccess(initToastMessage); + }, 100); + + return () => clearTimeout(timeout); + }, [dispatch, initToastMessage, setInitToastMessage]); const assetsSegmentControlRef = useAssetsSegmentControlRef(); diff --git a/src/app/pages/Home/OtherComponents/Tokens/components/AddTokenModal/AddTokenForm.tsx b/src/app/pages/Home/OtherComponents/Tokens/components/AddTokenModal/AddTokenForm.tsx index 783f898b6a..9d3c438b75 100644 --- a/src/app/pages/Home/OtherComponents/Tokens/components/AddTokenModal/AddTokenForm.tsx +++ b/src/app/pages/Home/OtherComponents/Tokens/components/AddTokenModal/AddTokenForm.tsx @@ -359,13 +359,13 @@ export const AddTokenForm = memo( onClean={cleanContractAddress} placeholder={isTezosChainSelected ? 'KT1v9CmPy…' : '0x0f5d2fb2…'} errorCaption={errors.address?.message} - containerClassName="mb-6" + containerClassName={forCollectible || isTezosChainSelected ? 'mb-3' : 'mb-1'} className="resize-none" /> {(forCollectible || isTezosChainSelected) && ( <> -
+

@@ -386,7 +386,7 @@ export const AddTokenForm = memo( cleanable={Boolean(tokenIdWithoutFallback) || tokenIdWithoutFallback === '0'} onClean={cleanTokenId} errorCaption={errors.id?.message} - containerClassName="mb-6" + containerClassName="mb-1" /> )} diff --git a/src/app/pages/Settings/reset-extension-modal.tsx b/src/app/pages/Settings/reset-extension-modal.tsx index 463ab2a3b4..4ba31cae96 100644 --- a/src/app/pages/Settings/reset-extension-modal.tsx +++ b/src/app/pages/Settings/reset-extension-modal.tsx @@ -57,6 +57,7 @@ export const ResetExtensionModal = memo(({ onClose }) labelContainerClassName="text-grey-2" placeholder={DEFAULT_PASSWORD_INPUT_PLACEHOLDER} errorCaption={errors.password?.message} + reserveSpaceForError={false} containerClassName="mb-2" testID={SettingsSelectors.passwordInput} /> diff --git a/src/app/templates/AccountsManagement/confirm-seed-phrase-access-modal.tsx b/src/app/templates/AccountsManagement/confirm-seed-phrase-access-modal.tsx index 0fa2dc1823..60cb8bf1f6 100644 --- a/src/app/templates/AccountsManagement/confirm-seed-phrase-access-modal.tsx +++ b/src/app/templates/AccountsManagement/confirm-seed-phrase-access-modal.tsx @@ -57,6 +57,7 @@ export const ConfirmSeedPhraseAccessModal = memo diff --git a/src/app/templates/AccountsManagement/delete-wallet-modal.tsx b/src/app/templates/AccountsManagement/delete-wallet-modal.tsx index 0fc038e197..c5dfa326af 100644 --- a/src/app/templates/AccountsManagement/delete-wallet-modal.tsx +++ b/src/app/templates/AccountsManagement/delete-wallet-modal.tsx @@ -96,6 +96,7 @@ export const DeleteWalletModal = memo(({ onClose, select name="password" placeholder={DEFAULT_PASSWORD_INPUT_PLACEHOLDER} errorCaption={errors.password?.message} + reserveSpaceForError={false} containerClassName="mb-1" testID={AccountsManagementSelectors.passwordInput} /> diff --git a/src/app/templates/AccountsManagement/rename-wallet-modal.tsx b/src/app/templates/AccountsManagement/rename-wallet-modal.tsx index f2a48a321b..7c077593d4 100644 --- a/src/app/templates/AccountsManagement/rename-wallet-modal.tsx +++ b/src/app/templates/AccountsManagement/rename-wallet-modal.tsx @@ -66,6 +66,7 @@ export const RenameWalletModal = memo(({ onClose, select name="name" placeholder={selectedGroup.name} errorCaption={errors.name?.message} + reserveSpaceForError={false} containerClassName="mb-1.5" cleanable onClean={cleanWalletName} diff --git a/src/app/templates/CreatePasswordForm/index.tsx b/src/app/templates/CreatePasswordForm/index.tsx index 7708cdc50c..00cc4f5905 100644 --- a/src/app/templates/CreatePasswordForm/index.tsx +++ b/src/app/templates/CreatePasswordForm/index.tsx @@ -38,7 +38,7 @@ import { T, TID, t } from 'lib/i18n'; import { putToStorage } from 'lib/storage'; import { useStorage, useTempleClient } from 'lib/temple/front'; import { setMnemonicToBackup } from 'lib/temple/front/mnemonic-to-backup-keeper'; -import { SuccessfulImportToastContext } from 'lib/temple/front/successful-import-toast-context'; +import { SuccessfulInitToastContext } from 'lib/temple/front/successful-init-toast-context'; import { navigate } from 'lib/woozie'; import { createPasswordSelectors } from './selectors'; @@ -68,7 +68,7 @@ export const CreatePasswordForm = memo(({ seedPhrase: s const [, setShouldBackupMnemonic] = useStorage(SHOULD_BACKUP_MNEMONIC_STORAGE_KEY); const [bottomEdgeIsVisible, setBottomEdgeIsVisible] = useState(true); const { setOnboardingCompleted } = useOnboardingProgress(); - const [, setShouldShowImportToast] = useContext(SuccessfulImportToastContext); + const [, setInitToast] = useContext(SuccessfulInitToastContext); const dispatch = useDispatch(); @@ -128,7 +128,7 @@ export const CreatePasswordForm = memo(({ seedPhrase: s trackEvent('AnalyticsAndAdsEnabled', AnalyticsEventCategory.General, { accountPkh }, data.analytics); } if (seedPhraseToImport) { - setShouldShowImportToast(true); + setInitToast(t('importSuccessful')); } else { await setShouldBackupMnemonic(true); setMnemonicToBackup(seedPhrase); @@ -147,16 +147,16 @@ export const CreatePasswordForm = memo(({ seedPhrase: s } }, [ + setOnboardingCompleted, + submitting, dispatch, + setTermsAccepted, registerWallet, seedPhrase, seedPhraseToImport, - setTermsAccepted, - setOnboardingCompleted, - setShouldBackupMnemonic, - setShouldShowImportToast, - submitting, - trackEvent + trackEvent, + setInitToast, + setShouldBackupMnemonic ] ); diff --git a/src/app/templates/ImportAccountModal/forms/private-key.tsx b/src/app/templates/ImportAccountModal/forms/private-key.tsx index 5afdbba7b5..9b42b4cabc 100644 --- a/src/app/templates/ImportAccountModal/forms/private-key.tsx +++ b/src/app/templates/ImportAccountModal/forms/private-key.tsx @@ -99,7 +99,7 @@ export const PrivateKeyForm = memo(({ onSuccess }) => { errorCaption={errors.privateKey?.message ?? submitError} shouldShowErrorCaption className="resize-none" - containerClassName="mb-8" + containerClassName="mb-4" cleanable={Boolean(keyValue)} onClean={cleanPrivateKeyField} onChange={resetSubmitError} diff --git a/src/app/templates/ManualBackupModal/verify-seed-phrase-input/word-input.tsx b/src/app/templates/ManualBackupModal/verify-seed-phrase-input/word-input.tsx index 1867f017d5..f74517443b 100644 --- a/src/app/templates/ManualBackupModal/verify-seed-phrase-input/word-input.tsx +++ b/src/app/templates/ManualBackupModal/verify-seed-phrase-input/word-input.tsx @@ -26,6 +26,7 @@ export const WordInput = memo(({ wordIndex, active, value, testI
} + reserveSpaceForError={false} value={value} readOnly testID={testID} diff --git a/src/app/templates/NetworksSettings/add-network-modal/index.tsx b/src/app/templates/NetworksSettings/add-network-modal/index.tsx index 44a2e7aeff..a85400e9fe 100644 --- a/src/app/templates/NetworksSettings/add-network-modal/index.tsx +++ b/src/app/templates/NetworksSettings/add-network-modal/index.tsx @@ -156,14 +156,10 @@ export const AddNetworkModal = memo(({ isOpen, onClose }) - + -
+
(({ isOpen, onClose }) />
-
+
= { name, testnet }; if (signal.aborted) { - console.log('aborted addNetwork'); return; } diff --git a/src/app/templates/SeedPhraseInput/SeedWordInput.tsx b/src/app/templates/SeedPhraseInput/SeedWordInput.tsx index 11449bad80..ca6bb0e656 100644 --- a/src/app/templates/SeedPhraseInput/SeedWordInput.tsx +++ b/src/app/templates/SeedPhraseInput/SeedWordInput.tsx @@ -222,6 +222,7 @@ export const SeedWordInput: FC = ({ autoComplete="off" smallPaddings fieldWrapperBottomMargin={false} + reserveSpaceForError={false} testID={testID} onKeyDown={handleInputKeyDown} /> diff --git a/src/lib/temple/front/provider.tsx b/src/lib/temple/front/provider.tsx index 68f4b3285f..3bf8347488 100644 --- a/src/lib/temple/front/provider.tsx +++ b/src/lib/temple/front/provider.tsx @@ -7,18 +7,18 @@ import { CustomTezosChainIdContext } from 'lib/analytics'; import { ReadyTempleProvider } from 'temple/front/ready'; import { TempleClientProvider, useTempleClient } from './client'; -import { SuccessfulImportToastContext } from './successful-import-toast-context'; +import { SuccessfulInitToastContext } from './successful-init-toast-context'; export const TempleProvider: FC = ({ children }) => { usePushNotifications(); - const importToastState = useState(false); + const initToastState = useState(); return ( - + {children} - + ); diff --git a/src/lib/temple/front/successful-import-toast-context.ts b/src/lib/temple/front/successful-import-toast-context.ts deleted file mode 100644 index 31b1ff55fc..0000000000 --- a/src/lib/temple/front/successful-import-toast-context.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { createContext, Dispatch, SetStateAction } from 'react'; - -import { noop } from 'lodash'; - -type SuccessfulImportToastContextType = [boolean, Dispatch>]; - -export const SuccessfulImportToastContext = createContext([false, noop]); diff --git a/src/lib/temple/front/successful-init-toast-context.ts b/src/lib/temple/front/successful-init-toast-context.ts new file mode 100644 index 0000000000..570df49f0c --- /dev/null +++ b/src/lib/temple/front/successful-init-toast-context.ts @@ -0,0 +1,7 @@ +import { createContext, Dispatch, SetStateAction } from 'react'; + +import { noop } from 'lodash'; + +type SuccessfulInitToastContextType = [string | undefined, Dispatch>]; + +export const SuccessfulInitToastContext = createContext([undefined, noop]);