diff --git a/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-creates-a-transaction-via-footer-button-5-chromium-linux.png b/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-creates-a-transaction-via-footer-button-5-chromium-linux.png
index 7faf369647c50435999b5bed682446bbb3755b2d..94ee19d49d1ae63b55fbf2b9e7a7c0771b607640 100644
Binary files a/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-creates-a-transaction-via-footer-button-5-chromium-linux.png and b/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-creates-a-transaction-via-footer-button-5-chromium-linux.png differ
diff --git a/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-opens-individual-account-page-and-checks-that-filtering-is-working-1-chromium-linux.png b/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-opens-individual-account-page-and-checks-that-filtering-is-working-1-chromium-linux.png
index 623c76625f149b4c4ca542951ac28682af13bac5..d155399a88cc237103d1c0ef7977cbcc2820f6b6 100644
Binary files a/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-opens-individual-account-page-and-checks-that-filtering-is-working-1-chromium-linux.png and b/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-opens-individual-account-page-and-checks-that-filtering-is-working-1-chromium-linux.png differ
diff --git a/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-opens-individual-account-page-and-checks-that-filtering-is-working-3-chromium-linux.png b/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-opens-individual-account-page-and-checks-that-filtering-is-working-3-chromium-linux.png
index 78e8dc758e83ccc5e757410b5be2103d94c18371..2c233815a964b72a2031d58348742cbfe5792205 100644
Binary files a/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-opens-individual-account-page-and-checks-that-filtering-is-working-3-chromium-linux.png and b/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-opens-individual-account-page-and-checks-that-filtering-is-working-3-chromium-linux.png differ
diff --git a/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-opens-individual-account-page-and-checks-that-filtering-is-working-5-chromium-linux.png b/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-opens-individual-account-page-and-checks-that-filtering-is-working-5-chromium-linux.png
index 51e86751f51469bdf9ce19a2b809ec4249959e09..62f4c3567cdbeb063d6808fbe3890339ff08916a 100644
Binary files a/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-opens-individual-account-page-and-checks-that-filtering-is-working-5-chromium-linux.png and b/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-opens-individual-account-page-and-checks-that-filtering-is-working-5-chromium-linux.png differ
diff --git a/packages/desktop-client/src/components/Modals.tsx b/packages/desktop-client/src/components/Modals.tsx
index bcc1ade800f82e123f7f5037c1d642aacafcb33b..bdd7cc587c733b56ef18348f80ef283428469e16 100644
--- a/packages/desktop-client/src/components/Modals.tsx
+++ b/packages/desktop-client/src/components/Modals.tsx
@@ -6,16 +6,21 @@ import { useLocation } from 'react-router-dom';
 import { type State } from 'loot-core/src/client/state-types';
 import { type PopModalAction } from 'loot-core/src/client/state-types/modals';
 import { send } from 'loot-core/src/platform/client/fetch';
+import * as monthUtils from 'loot-core/src/shared/months';
 
 import { useActions } from '../hooks/useActions';
 import { useSyncServerStatus } from '../hooks/useSyncServerStatus';
 
-import { CategoryGroupMenu } from './modals/CategoryGroupMenu';
-import { CategoryMenu } from './modals/CategoryMenu';
-import { CloseAccount } from './modals/CloseAccount';
+import { AccountAutocompleteModal } from './modals/AccountAutocompleteModal';
+import { AccountMenuModal } from './modals/AccountMenuModal';
+import { CategoryAutocompleteModal } from './modals/CategoryAutocompleteModal';
+import { CategoryGroupMenuModal } from './modals/CategoryGroupMenuModal';
+import { CategoryMenuModal } from './modals/CategoryMenuModal';
+import { CloseAccountModal } from './modals/CloseAccountModal';
 import { ConfirmCategoryDelete } from './modals/ConfirmCategoryDelete';
 import { ConfirmTransactionEdit } from './modals/ConfirmTransactionEdit';
 import { ConfirmUnlinkAccount } from './modals/ConfirmUnlinkAccount';
+import { CoverModal } from './modals/CoverModal';
 import { CreateAccount } from './modals/CreateAccount';
 import { CreateEncryptionKey } from './modals/CreateEncryptionKey';
 import { CreateLocalAccount } from './modals/CreateLocalAccount';
@@ -24,22 +29,30 @@ import { EditRule } from './modals/EditRule';
 import { FixEncryptionKey } from './modals/FixEncryptionKey';
 import { GoCardlessExternalMsg } from './modals/GoCardlessExternalMsg';
 import { GoCardlessInitialise } from './modals/GoCardlessInitialise';
+import { HoldBufferModal } from './modals/HoldBufferModal';
 import { ImportTransactions } from './modals/ImportTransactions';
 import { LoadBackup } from './modals/LoadBackup';
 import { ManageRulesModal } from './modals/ManageRulesModal';
 import { MergeUnusedPayees } from './modals/MergeUnusedPayees';
 import { Notes } from './modals/Notes';
+import { PayeeAutocompleteModal } from './modals/PayeeAutocompleteModal';
 import { PlaidExternalMsg } from './modals/PlaidExternalMsg';
-import { ReportBudgetSummary } from './modals/ReportBudgetSummary';
-import { RolloverBudgetSummary } from './modals/RolloverBudgetSummary';
+import { ReportBalanceMenuModal } from './modals/ReportBalanceMenuModal';
+import { ReportBudgetSummaryModal } from './modals/ReportBudgetSummaryModal';
+import { RolloverBalanceMenuModal } from './modals/RolloverBalanceMenuModal';
+import { RolloverBudgetSummaryModal } from './modals/RolloverBudgetSummaryModal';
+import { RolloverToBudgetMenuModal } from './modals/RolloverToBudgetMenuModal';
+import { ScheduledTransactionMenuModal } from './modals/ScheduledTransactionMenuModal';
 import { SelectLinkedAccounts } from './modals/SelectLinkedAccounts';
 import { SimpleFinInitialise } from './modals/SimpleFinInitialise';
-import { SingleInput } from './modals/SingleInput';
+import { SingleInputModal } from './modals/SingleInputModal';
 import { SwitchBudgetType } from './modals/SwitchBudgetType';
+import { TransferModal } from './modals/TransferModal';
 import { DiscoverSchedules } from './schedules/DiscoverSchedules';
 import { PostsOfflineNotification } from './schedules/PostsOfflineNotification';
 import { ScheduleDetails } from './schedules/ScheduleDetails';
 import { ScheduleLink } from './schedules/ScheduleLink';
+import { NamespaceContext } from './spreadsheet/NamespaceContext';
 
 export type CommonModalProps = {
   onClose: () => PopModalAction;
@@ -97,12 +110,11 @@ export function Modals() {
 
         case 'close-account':
           return (
-            <CloseAccount
+            <CloseAccountModal
               modalProps={modalProps}
               account={options.account}
               balance={options.balance}
               canDelete={options.canDelete}
-              actions={actions}
             />
           );
 
@@ -255,9 +267,51 @@ export function Modals() {
             />
           );
 
+        case 'category-autocomplete':
+          return (
+            <CategoryAutocompleteModal
+              key={name}
+              modalProps={modalProps}
+              autocompleteProps={{
+                value: null,
+                categoryGroups: options.categoryGroups,
+                onSelect: options.onSelect,
+                showHiddenCategories: options.showHiddenCategories,
+              }}
+              onClose={options.onClose}
+            />
+          );
+
+        case 'account-autocomplete':
+          return (
+            <AccountAutocompleteModal
+              key={name}
+              modalProps={modalProps}
+              autocompleteProps={{
+                value: null,
+                onSelect: options.onSelect,
+                includeClosedAccounts: options.includeClosedAccounts,
+              }}
+              onClose={options.onClose}
+            />
+          );
+
+        case 'payee-autocomplete':
+          return (
+            <PayeeAutocompleteModal
+              key={name}
+              modalProps={modalProps}
+              autocompleteProps={{
+                value: null,
+                onSelect: options.onSelect,
+              }}
+              onClose={options.onClose}
+            />
+          );
+
         case 'new-category':
           return (
-            <SingleInput
+            <SingleInputModal
               modalProps={modalProps}
               title="New Category"
               inputPlaceholder="Category name"
@@ -269,7 +323,7 @@ export function Modals() {
 
         case 'new-category-group':
           return (
-            <SingleInput
+            <SingleInputModal
               modalProps={modalProps}
               title="New Category Group"
               inputPlaceholder="Category group name"
@@ -281,17 +335,22 @@ export function Modals() {
 
         case 'rollover-budget-summary':
           return (
-            <RolloverBudgetSummary
+            <NamespaceContext.Provider
               key={name}
-              modalProps={modalProps}
-              month={options.month}
-              onBudgetAction={options.onBudgetAction}
-            />
+              value={monthUtils.sheetForMonth(options.month)}
+            >
+              <RolloverBudgetSummaryModal
+                key={name}
+                modalProps={modalProps}
+                month={options.month}
+                onBudgetAction={options.onBudgetAction}
+              />
+            </NamespaceContext.Provider>
           );
 
         case 'report-budget-summary':
           return (
-            <ReportBudgetSummary
+            <ReportBudgetSummaryModal
               key={name}
               modalProps={modalProps}
               month={options.month}
@@ -348,9 +407,23 @@ export function Modals() {
             />
           );
 
+        case 'account-menu':
+          return (
+            <AccountMenuModal
+              key={name}
+              modalProps={modalProps}
+              accountId={options.accountId}
+              onSave={options.onSave}
+              onEditNotes={options.onEditNotes}
+              onCloseAccount={options.onCloseAccount}
+              onReopenAccount={options.onReopenAccount}
+              onClose={options.onClose}
+            />
+          );
+
         case 'category-menu':
           return (
-            <CategoryMenu
+            <CategoryMenuModal
               key={name}
               modalProps={modalProps}
               categoryId={options.categoryId}
@@ -363,7 +436,7 @@ export function Modals() {
 
         case 'category-group-menu':
           return (
-            <CategoryGroupMenu
+            <CategoryGroupMenuModal
               key={name}
               modalProps={modalProps}
               groupId={options.groupId}
@@ -387,6 +460,95 @@ export function Modals() {
             />
           );
 
+        case 'rollover-balance-menu':
+          return (
+            <NamespaceContext.Provider
+              key={name}
+              value={monthUtils.sheetForMonth(options.month)}
+            >
+              <RolloverBalanceMenuModal
+                modalProps={modalProps}
+                categoryId={options.categoryId}
+                onCarryover={options.onCarryover}
+                onTransfer={options.onTransfer}
+                onCover={options.onCover}
+              />
+            </NamespaceContext.Provider>
+          );
+
+        case 'rollover-to-budget-menu':
+          return (
+            <NamespaceContext.Provider
+              key={name}
+              value={monthUtils.sheetForMonth(options.month)}
+            >
+              <RolloverToBudgetMenuModal
+                modalProps={modalProps}
+                onTransfer={options.onTransfer}
+                onHoldBuffer={options.onHoldBuffer}
+                onResetHoldBuffer={options.onResetHoldBuffer}
+              />
+            </NamespaceContext.Provider>
+          );
+
+        case 'hold-buffer':
+          return (
+            <NamespaceContext.Provider
+              key={name}
+              value={monthUtils.sheetForMonth(options.month)}
+            >
+              <HoldBufferModal
+                modalProps={modalProps}
+                month={options.month}
+                onSubmit={options.onSubmit}
+              />
+            </NamespaceContext.Provider>
+          );
+
+        case 'report-balance-menu':
+          return (
+            <NamespaceContext.Provider
+              key={name}
+              value={monthUtils.sheetForMonth(options.month)}
+            >
+              <ReportBalanceMenuModal
+                modalProps={modalProps}
+                categoryId={options.categoryId}
+                onCarryover={options.onCarryover}
+              />
+            </NamespaceContext.Provider>
+          );
+
+        case 'transfer':
+          return (
+            <TransferModal
+              modalProps={modalProps}
+              title={options.title}
+              amount={options.amount}
+              onSubmit={options.onSubmit}
+              showToBeBudgeted={options.showToBeBudgeted}
+            />
+          );
+
+        case 'cover':
+          return (
+            <CoverModal
+              modalProps={modalProps}
+              categoryId={options.categoryId}
+              onSubmit={options.onSubmit}
+            />
+          );
+
+        case 'scheduled-transaction-menu':
+          return (
+            <ScheduledTransactionMenuModal
+              modalProps={modalProps}
+              transactionId={options.transactionId}
+              onPost={options.onPost}
+              onSkip={options.onSkip}
+            />
+          );
+
         default:
           console.error('Unknown modal:', name);
           return null;
diff --git a/packages/desktop-client/src/components/autocomplete/AccountAutocomplete.tsx b/packages/desktop-client/src/components/autocomplete/AccountAutocomplete.tsx
index e6efee159a208bf5201d5bccf62984da0097ffb8..bc053ed99b2de88a74cf0193721133523fdaca9d 100644
--- a/packages/desktop-client/src/components/autocomplete/AccountAutocomplete.tsx
+++ b/packages/desktop-client/src/components/autocomplete/AccountAutocomplete.tsx
@@ -166,7 +166,7 @@ type AccountItemProps = {
   embedded?: boolean;
 };
 
-export function AccountItem({
+function AccountItem({
   item,
   className,
   highlighted,
diff --git a/packages/desktop-client/src/components/autocomplete/CategoryAutocomplete.tsx b/packages/desktop-client/src/components/autocomplete/CategoryAutocomplete.tsx
index fc2617b930fc47e1447fc38dcebc05ce9740ee38..8ff9d228ff1e02a5bd12ff2b94edcf90eec35931 100644
--- a/packages/desktop-client/src/components/autocomplete/CategoryAutocomplete.tsx
+++ b/packages/desktop-client/src/components/autocomplete/CategoryAutocomplete.tsx
@@ -297,7 +297,7 @@ type CategoryItemProps = {
   embedded?: boolean;
 };
 
-export function CategoryItem({
+function CategoryItem({
   item,
   className,
   style,
diff --git a/packages/desktop-client/src/components/autocomplete/PayeeAutocomplete.tsx b/packages/desktop-client/src/components/autocomplete/PayeeAutocomplete.tsx
index 5d660aab80ffa56fc70f92befff606c5fad1a303..a65ed413d7d421c0c995cf80f7f47918af91251c 100644
--- a/packages/desktop-client/src/components/autocomplete/PayeeAutocomplete.tsx
+++ b/packages/desktop-client/src/components/autocomplete/PayeeAutocomplete.tsx
@@ -398,6 +398,7 @@ type CreatePayeeButtonProps = {
   style?: CSSProperties;
 };
 
+// eslint-disable-next-line import/no-unused-modules
 export function CreatePayeeButton({
   Icon,
   payeeName,
@@ -471,7 +472,7 @@ type PayeeItemProps = {
   embedded?: boolean;
 };
 
-export function PayeeItem({
+function PayeeItem({
   item,
   className,
   highlighted,
diff --git a/packages/desktop-client/src/components/budget/index.tsx b/packages/desktop-client/src/components/budget/index.tsx
index cad97746ba6d82c210c963d068153b00549495b9..a95139bf7201dd12bf2018c95f66820a7686327e 100644
--- a/packages/desktop-client/src/components/budget/index.tsx
+++ b/packages/desktop-client/src/components/budget/index.tsx
@@ -28,6 +28,7 @@ import { useLocalPref } from '../../hooks/useLocalPref';
 import { useNavigate } from '../../hooks/useNavigate';
 import { styles } from '../../style';
 import { View } from '../common/View';
+import { NamespaceContext } from '../spreadsheet/NamespaceContext';
 import {
   SWITCH_BUDGET_MESSAGE_TYPE,
   TitlebarContext,
@@ -404,7 +405,11 @@ function BudgetInner(props: BudgetInnerProps) {
     );
   }
 
-  return <View style={{ flex: 1 }}>{table}</View>;
+  return (
+    <NamespaceContext.Provider value={monthUtils.sheetForMonth(startMonth)}>
+      <View style={{ flex: 1 }}>{table}</View>
+    </NamespaceContext.Provider>
+  );
 }
 
 const RolloverBudgetSummary = memo<{ month: string }>(props => {
diff --git a/packages/desktop-client/src/components/budget/report/BalanceMenu.tsx b/packages/desktop-client/src/components/budget/report/BalanceMenu.tsx
index 0878a98310bdd0f24f2d36312e8818778ac8142d..0673620ff3734c2f57700538483c2d2318da71ef 100644
--- a/packages/desktop-client/src/components/budget/report/BalanceMenu.tsx
+++ b/packages/desktop-client/src/components/budget/report/BalanceMenu.tsx
@@ -28,7 +28,7 @@ export function BalanceMenu({
             onCarryover?.(!carryover);
             break;
           default:
-            throw new Error(`Unsupported item: ${name}`);
+            throw new Error(`Unrecognized menu option: ${name}`);
         }
       }}
       items={[
diff --git a/packages/desktop-client/src/components/budget/rollover/BalanceMenu.tsx b/packages/desktop-client/src/components/budget/rollover/BalanceMenu.tsx
index 803fcbe58b056f100bfabb632f0c8d503562ae48..3ec3c5f0f6c92d706cfe4c0c3427278f7db3da24 100644
--- a/packages/desktop-client/src/components/budget/rollover/BalanceMenu.tsx
+++ b/packages/desktop-client/src/components/budget/rollover/BalanceMenu.tsx
@@ -39,7 +39,7 @@ export function BalanceMenu({
             onCover?.();
             break;
           default:
-            throw new Error(`Unsupported item: ${name}`);
+            throw new Error(`Unrecognized menu option: ${name}`);
         }
       }}
       items={[
diff --git a/packages/desktop-client/src/components/budget/rollover/RolloverContext.tsx b/packages/desktop-client/src/components/budget/rollover/RolloverContext.tsx
index ea05cd8737444ee10c9e1b6a6f1e1c6b1c7813da..bf68c07afaa6cdad2afee0ba0c8a2320a55d6697 100644
--- a/packages/desktop-client/src/components/budget/rollover/RolloverContext.tsx
+++ b/packages/desktop-client/src/components/budget/rollover/RolloverContext.tsx
@@ -9,7 +9,7 @@ type RolloverContextDefinition = {
   currentMonth: string;
 };
 
-const Context = createContext<RolloverContextDefinition>({
+const RolloverContext = createContext<RolloverContextDefinition>({
   summaryCollapsed: false,
   onBudgetAction: () => {
     throw new Error('Unitialised context method called: onBudgetAction');
@@ -34,7 +34,7 @@ export function RolloverProvider({
   const currentMonth = monthUtils.currentMonth();
 
   return (
-    <Context.Provider
+    <RolloverContext.Provider
       value={{
         currentMonth,
         summaryCollapsed,
@@ -43,10 +43,10 @@ export function RolloverProvider({
       }}
     >
       {children}
-    </Context.Provider>
+    </RolloverContext.Provider>
   );
 }
 
 export function useRollover() {
-  return useContext(Context);
+  return useContext(RolloverContext);
 }
diff --git a/packages/desktop-client/src/components/budget/rollover/budgetsummary/ToBudgetMenu.tsx b/packages/desktop-client/src/components/budget/rollover/budgetsummary/ToBudgetMenu.tsx
index 183e7d28753c9ee11a208839b19bf924a10795b2..95cf54a8f14c7cb66634b76059f1c6bab2e1acc4 100644
--- a/packages/desktop-client/src/components/budget/rollover/budgetsummary/ToBudgetMenu.tsx
+++ b/packages/desktop-client/src/components/budget/rollover/budgetsummary/ToBudgetMenu.tsx
@@ -31,7 +31,7 @@ export function ToBudgetMenu({
             onResetHoldBuffer?.();
             break;
           default:
-            throw new Error(`Unsupported item: ${name}`);
+            throw new Error(`Unrecognized menu option: ${name}`);
         }
       }}
       items={[
diff --git a/packages/desktop-client/src/components/mobile/MobileForms.tsx b/packages/desktop-client/src/components/mobile/MobileForms.tsx
index 6141192bdab16a9418a6307e619a85f3af070c36..9b5394a024a9b5f5c5b879f62cd825fda8eb9b10 100644
--- a/packages/desktop-client/src/components/mobile/MobileForms.tsx
+++ b/packages/desktop-client/src/components/mobile/MobileForms.tsx
@@ -1,5 +1,5 @@
 import React, {
-  type ComponentPropsWithoutRef,
+  type ComponentPropsWithRef,
   forwardRef,
   type ReactNode,
 } from 'react';
@@ -45,7 +45,7 @@ const valueStyle = {
   height: styles.mobileMinHeight,
 };
 
-type InputFieldProps = ComponentPropsWithoutRef<typeof Input>;
+type InputFieldProps = ComponentPropsWithRef<typeof Input>;
 
 export const InputField = forwardRef<HTMLInputElement, InputFieldProps>(
   ({ disabled, style, onUpdate, ...props }, ref) => {
@@ -72,7 +72,7 @@ export const InputField = forwardRef<HTMLInputElement, InputFieldProps>(
 
 InputField.displayName = 'InputField';
 
-type TapFieldProps = ComponentPropsWithoutRef<typeof Button> & {
+type TapFieldProps = ComponentPropsWithRef<typeof Button> & {
   rightContent?: ReactNode;
 };
 
diff --git a/packages/desktop-client/src/components/mobile/accounts/Account.jsx b/packages/desktop-client/src/components/mobile/accounts/Account.jsx
index 25c0bd4b17f0bd76fd2c47ca8bdf23e17638f7a1..4a07c391e6ede2b600d98f746b7ca4f4e882dd8d 100644
--- a/packages/desktop-client/src/components/mobile/accounts/Account.jsx
+++ b/packages/desktop-client/src/components/mobile/accounts/Account.jsx
@@ -12,7 +12,7 @@ import {
 } from 'loot-core/src/client/data-hooks/schedules';
 import * as queries from 'loot-core/src/client/queries';
 import { pagedQuery } from 'loot-core/src/client/query-helpers';
-import { listen } from 'loot-core/src/platform/client/fetch';
+import { listen, send } from 'loot-core/src/platform/client/fetch';
 import {
   isPreviewId,
   ungroupTransactions,
@@ -126,6 +126,10 @@ export function Account(props) {
     updateQuery(query);
   }, [makeRootQuery, updateQuery]);
 
+  const refetchTransactions = () => {
+    paged.current?.run();
+  };
+
   useEffect(() => {
     let unlisten;
 
@@ -137,7 +141,7 @@ export function Account(props) {
             tables.includes('category_mapping') ||
             tables.includes('payee_mapping')
           ) {
-            paged.current?.run();
+            refetchTransactions();
           }
 
           if (tables.includes('payees') || tables.includes('payee_mapping')) {
@@ -222,6 +226,23 @@ export function Account(props) {
     // details of how the native app used to handle preview transactions here can be found at commit 05e58279
     if (!isPreviewId(transaction.id)) {
       navigate(`transactions/${transaction.id}`);
+    } else {
+      dispatch(
+        actions.pushModal('scheduled-transaction-menu', {
+          transactionId: transaction.id,
+          onPost: async transactionId => {
+            const parts = transactionId.split('/');
+            await send('schedule/post-transaction', { id: parts[1] });
+            refetchTransactions();
+            dispatch(actions.collapseModals('scheduled-transaction-menu'));
+          },
+          onSkip: async transactionId => {
+            const parts = transactionId.split('/');
+            await send('schedule/skip-next-date', { id: parts[1] });
+            dispatch(actions.collapseModals('scheduled-transaction-menu'));
+          },
+        }),
+      );
     }
   };
 
diff --git a/packages/desktop-client/src/components/mobile/accounts/AccountDetails.jsx b/packages/desktop-client/src/components/mobile/accounts/AccountDetails.jsx
index b73909fd337bae126f03fb64ea4b8d23436817c0..be92e97ffa6fb4d35793e008ae2433cd03ade6de 100644
--- a/packages/desktop-client/src/components/mobile/accounts/AccountDetails.jsx
+++ b/packages/desktop-client/src/components/mobile/accounts/AccountDetails.jsx
@@ -1,7 +1,14 @@
 import React, { useState, useMemo } from 'react';
 import { useDispatch } from 'react-redux';
 
-import { syncAndDownload } from 'loot-core/client/actions';
+import {
+  openAccountCloseModal,
+  pushModal,
+  reopenAccount,
+  syncAndDownload,
+  updateAccount,
+} from 'loot-core/client/actions';
+import { send } from 'loot-core/platform/client/fetch';
 
 import { SvgAdd } from '../../../icons/v1';
 import { SvgSearchAlternate } from '../../../icons/v2';
@@ -9,6 +16,7 @@ import { styles, theme } from '../../../style';
 import { ButtonLink } from '../../common/ButtonLink';
 import { InputWithContent } from '../../common/InputWithContent';
 import { Label } from '../../common/Label';
+import { Text } from '../../common/Text';
 import { View } from '../../common/View';
 import { MobileBackButton } from '../../MobileBackButton';
 import { Page } from '../../Page';
@@ -60,6 +68,79 @@ function TransactionSearchInput({ accountName, onSearch }) {
   );
 }
 
+function AccountName({ account, pending, failed }) {
+  const dispatch = useDispatch();
+
+  const onSave = account => {
+    dispatch(updateAccount(account));
+  };
+
+  const onSaveNotes = async (id, notes) => {
+    await send('notes-save', { id, note: notes });
+  };
+
+  const onEditNotes = () => {
+    dispatch(
+      pushModal('notes', {
+        id: account.id,
+        name: account.name,
+        onSave: onSaveNotes,
+      }),
+    );
+  };
+
+  const onCloseAccount = () => {
+    dispatch(openAccountCloseModal(account.id));
+  };
+
+  const onReopenAccount = () => {
+    dispatch(reopenAccount(account.id));
+  };
+
+  const onClick = () => {
+    dispatch(
+      pushModal('account-menu', {
+        accountId: account.id,
+        onSave,
+        onEditNotes,
+        onCloseAccount,
+        onReopenAccount,
+      }),
+    );
+  };
+  return (
+    <View
+      style={{
+        flexDirection: 'row',
+      }}
+    >
+      {account.bankId && (
+        <div
+          style={{
+            margin: 'auto',
+            marginRight: 5,
+            width: 8,
+            height: 8,
+            borderRadius: 8,
+            backgroundColor: pending
+              ? theme.sidebarItemBackgroundPending
+              : failed
+                ? theme.sidebarItemBackgroundFailed
+                : theme.sidebarItemBackgroundPositive,
+            transition: 'transform .3s',
+          }}
+        />
+      )}
+      <Text
+        style={{ ...styles.underlinedText, ...styles.lineClamp(2) }}
+        onClick={onClick}
+      >
+        {`${account.closed ? 'Closed: ' : ''}${account.name}`}
+      </Text>
+    </View>
+  );
+}
+
 export function AccountDetails({
   account,
   pending,
@@ -89,32 +170,7 @@ export function AccountDetails({
   return (
     <Page
       title={
-        !account.bankId ? (
-          account.name
-        ) : (
-          <View
-            style={{
-              flexDirection: 'row',
-            }}
-          >
-            <div
-              style={{
-                margin: 'auto',
-                marginRight: 3,
-                width: 8,
-                height: 8,
-                borderRadius: 8,
-                backgroundColor: pending
-                  ? theme.sidebarItemBackgroundPending
-                  : failed
-                    ? theme.sidebarItemBackgroundFailed
-                    : theme.sidebarItemBackgroundPositive,
-                transition: 'transform .3s',
-              }}
-            />
-            {account.name}
-          </View>
-        )
+        <AccountName account={account} pending={pending} failed={failed} />
       }
       headerLeftContent={<MobileBackButton />}
       headerRightContent={
diff --git a/packages/desktop-client/src/components/mobile/budget/BudgetTable.jsx b/packages/desktop-client/src/components/mobile/budget/BudgetTable.jsx
index 92bdf7fd60203187defcf5b60cf993e17000f606..eed6c851f02713335e26a4eef55f051acc72d4ee 100644
--- a/packages/desktop-client/src/components/mobile/budget/BudgetTable.jsx
+++ b/packages/desktop-client/src/components/mobile/budget/BudgetTable.jsx
@@ -3,7 +3,7 @@ import { useDispatch } from 'react-redux';
 
 import memoizeOne from 'memoize-one';
 
-import { pushModal } from 'loot-core/client/actions';
+import { collapseModals, pushModal } from 'loot-core/client/actions';
 import { rolloverBudget, reportBudget } from 'loot-core/src/client/queries';
 import * as monthUtils from 'loot-core/src/shared/months';
 
@@ -21,8 +21,6 @@ import {
 import { useResponsive } from '../../../ResponsiveProvider';
 import { theme, styles } from '../../../style';
 import { BalanceWithCarryover } from '../../budget/BalanceWithCarryover';
-import { BalanceTooltip as ReportBudgetBalanceTooltip } from '../../budget/report/BalanceTooltip';
-import { BalanceTooltip as RolloverBudgetBalanceTooltip } from '../../budget/rollover/BalanceTooltip';
 import { makeAmountGrey } from '../../budget/util';
 import { Button } from '../../common/Button';
 import { Card } from '../../common/Card';
@@ -32,19 +30,13 @@ import { Text } from '../../common/Text';
 import { View } from '../../common/View';
 import { Page } from '../../Page';
 import { CellValue } from '../../spreadsheet/CellValue';
-import { NamespaceContext } from '../../spreadsheet/NamespaceContext';
 import { useFormat } from '../../spreadsheet/useFormat';
 import { useSheetValue } from '../../spreadsheet/useSheetValue';
 import { Tooltip, useTooltip } from '../../tooltips';
 import { AmountInput } from '../../util/AmountInput';
 import { MOBILE_NAV_HEIGHT } from '../MobileNavTabs';
 import { PullToRefresh } from '../PullToRefresh';
-// import {
-//   AmountAccessoryContext,
-//   MathOperations
-// } from '../mobile/AmountInput';
 
-// import { DragDrop, Draggable, Droppable, DragDropHighlight } from './dragdrop';
 import { ListItem, ROW_HEIGHT } from './ListItem';
 
 function ToBudget({ toBudget, onClick }) {
@@ -257,10 +249,11 @@ const ExpenseCategory = memo(function ExpenseCategory({
   showBudgetedCol,
 }) {
   const opacity = blank ? 0 : 1;
-  const balanceTooltip = useTooltip();
 
+  const [budgetType = 'rollover'] = useLocalPref('budgetType');
   const [isEditingBudget, setIsEditingBudget] = useState(false);
   const { onRequestActiveEdit, onClearActiveEdit } = useSingleActiveEditForm();
+  const dispatch = useDispatch();
 
   const onEditBudget = () => {
     onRequestActiveEdit(`${category.id}-budget`, () => {
@@ -269,23 +262,64 @@ const ExpenseCategory = memo(function ExpenseCategory({
     });
   };
 
-  const onOpenBalanceActionMenu = () => {
-    onRequestActiveEdit(`${category.id}-balance`, () => {
-      balanceTooltip.open();
-      return () => balanceTooltip.close();
+  const onCarryover = carryover => {
+    onBudgetAction(month, 'carryover', {
+      category: category.id,
+      flag: carryover,
     });
+    dispatch(collapseModals(`${budgetType}-balance-menu`));
   };
 
-  const listItemRef = useRef();
+  const catBalance = useSheetValue(
+    type === 'rollover'
+      ? rolloverBudget.catBalance(category.id)
+      : reportBudget.catBalance(category.id),
+  );
 
-  const _onBudgetAction = (monthIndex, action, arg) => {
-    onBudgetAction?.(
-      monthUtils.getMonthFromIndex(monthUtils.getYear(month), monthIndex),
-      action,
-      arg,
+  const onTransfer = () => {
+    dispatch(
+      pushModal('transfer', {
+        title: `Transfer: ${category.name}`,
+        amount: catBalance,
+        onSubmit: (amount, toCategoryId) => {
+          onBudgetAction(month, 'transfer-category', {
+            amount,
+            from: category.id,
+            to: toCategoryId,
+          });
+        },
+        showToBeBudgeted: true,
+      }),
     );
   };
 
+  const onCover = () => {
+    dispatch(
+      pushModal('cover', {
+        categoryId: category.id,
+        onSubmit: fromCategoryId => {
+          onBudgetAction(month, 'cover', {
+            to: category.id,
+            from: fromCategoryId,
+          });
+        },
+      }),
+    );
+  };
+
+  const onOpenBalanceActionMenu = () => {
+    dispatch(
+      pushModal(`${budgetType}-balance-menu`, {
+        categoryId: category.id,
+        month,
+        onCarryover,
+        ...(budgetType === 'rollover' && { onTransfer, onCover }),
+      }),
+    );
+  };
+
+  const listItemRef = useRef();
+
   const content = (
     <ListItem
       style={{
@@ -363,11 +397,7 @@ const ExpenseCategory = memo(function ExpenseCategory({
             height: ROW_HEIGHT,
           }}
         >
-          <span
-            role="button"
-            onPointerUp={() => onOpenBalanceActionMenu?.()}
-            onPointerDown={e => e.preventDefault()}
-          >
+          <span role="button" onClick={() => onOpenBalanceActionMenu?.()}>
             <BalanceWithCarryover
               carryover={carryover}
               balance={balance}
@@ -378,30 +408,6 @@ const ExpenseCategory = memo(function ExpenseCategory({
                 ...styles.underlinedText,
               }}
             />
-            {balanceTooltip.isOpen &&
-              (type === 'report' ? (
-                <ReportBudgetBalanceTooltip
-                  offset={5}
-                  categoryId={category.id}
-                  tooltip={balanceTooltip}
-                  monthIndex={monthUtils.getMonthIndex(month)}
-                  onBudgetAction={_onBudgetAction}
-                  onClose={() => {
-                    onClearActiveEdit();
-                  }}
-                />
-              ) : (
-                <RolloverBudgetBalanceTooltip
-                  offset={5}
-                  categoryId={category.id}
-                  tooltip={balanceTooltip}
-                  monthIndex={monthUtils.getMonthIndex(month)}
-                  onBudgetAction={_onBudgetAction}
-                  onClose={() => {
-                    onClearActiveEdit();
-                  }}
-                />
-              ))}
           </span>
         </View>
       </View>
@@ -1172,255 +1178,253 @@ export function BudgetTable({
   };
 
   return (
-    <NamespaceContext.Provider value={monthUtils.sheetForMonth(month, type)}>
-      <Page
-        padding={0}
-        title={
-          <MonthSelector
-            month={month}
-            monthBounds={monthBounds}
-            onPrevMonth={onPrevMonth}
-            onNextMonth={onNextMonth}
+    <Page
+      padding={0}
+      title={
+        <MonthSelector
+          month={month}
+          monthBounds={monthBounds}
+          onPrevMonth={onPrevMonth}
+          onNextMonth={onNextMonth}
+        />
+      }
+      headerRightContent={
+        !editMode ? (
+          <BudgetPageMenu
+            onEditMode={onEditMode}
+            onToggleHiddenCategories={onToggleHiddenCategories}
+            onSwitchBudgetType={_onSwitchBudgetType}
           />
-        }
-        headerRightContent={
-          !editMode ? (
-            <BudgetPageMenu
-              onEditMode={onEditMode}
-              onToggleHiddenCategories={onToggleHiddenCategories}
-              onSwitchBudgetType={_onSwitchBudgetType}
-            />
-          ) : (
-            <Button
-              type="bare"
-              hoveredStyle={{
-                color: theme.mobileHeaderText,
-                background: theme.mobileHeaderTextHover,
-              }}
-              style={{
-                ...styles.noTapHighlight,
-                ...styles.text,
-                backgroundColor: 'transparent',
-                color: theme.mobileHeaderText,
-              }}
-              onClick={() => onEditMode?.(false)}
-            >
-              Done
-            </Button>
-          )
-        }
-        style={{ flex: 1 }}
+        ) : (
+          <Button
+            type="bare"
+            hoveredStyle={{
+              color: theme.mobileHeaderText,
+              background: theme.mobileHeaderTextHover,
+            }}
+            style={{
+              ...styles.noTapHighlight,
+              ...styles.text,
+              backgroundColor: 'transparent',
+              color: theme.mobileHeaderText,
+            }}
+            onClick={() => onEditMode?.(false)}
+          >
+            Done
+          </Button>
+        )
+      }
+      style={{ flex: 1 }}
+    >
+      <View
+        style={{
+          flexDirection: 'row',
+          flexShrink: 0,
+          padding: 10,
+          paddingRight: 14,
+          backgroundColor: theme.tableRowHeaderBackground,
+          borderBottomWidth: 1,
+          borderColor: theme.tableBorder,
+        }}
       >
-        <View
-          style={{
-            flexDirection: 'row',
-            flexShrink: 0,
-            padding: 10,
-            paddingRight: 14,
-            backgroundColor: theme.tableRowHeaderBackground,
-            borderBottomWidth: 1,
-            borderColor: theme.tableBorder,
-          }}
-        >
-          {type === 'report' ? (
-            <Saved
-              projected={month >= monthUtils.currentMonth()}
-              onClick={onShowBudgetSummary}
-            />
-          ) : (
-            <ToBudget
-              toBudget={rolloverBudget.toBudget}
-              onClick={onShowBudgetSummary}
-            />
-          )}
-          <View style={{ flex: 1 }} />
-          {(show3Cols || !showSpentColumn) && (
-            <Button
-              type="bare"
-              disabled={show3Cols}
-              onClick={toggleDisplay}
+        {type === 'report' ? (
+          <Saved
+            projected={month >= monthUtils.currentMonth()}
+            onClick={onShowBudgetSummary}
+          />
+        ) : (
+          <ToBudget
+            toBudget={rolloverBudget.toBudget}
+            onClick={onShowBudgetSummary}
+          />
+        )}
+        <View style={{ flex: 1 }} />
+        {(show3Cols || !showSpentColumn) && (
+          <Button
+            type="bare"
+            disabled={show3Cols}
+            onClick={toggleDisplay}
+            style={{
+              ...buttonStyle,
+              padding: '0 8px',
+              margin: '0 -8px',
+              background:
+                !showSpentColumn && !show3Cols
+                  ? `linear-gradient(-45deg, ${theme.formInputBackgroundSelection} 8px, transparent 0)`
+                  : null,
+            }}
+          >
+            <View
               style={{
-                ...buttonStyle,
-                padding: '0 8px',
-                margin: '0 -8px',
-                background:
-                  !showSpentColumn && !show3Cols
-                    ? `linear-gradient(-45deg, ${theme.formInputBackgroundSelection} 8px, transparent 0)`
-                    : null,
+                flexBasis: 90,
+                width: 90,
+                justifyContent: 'center',
+                alignItems: 'flex-end',
               }}
             >
-              <View
+              <Label
+                title="BUDGETED"
+                style={{ color: theme.buttonNormalText }}
+              />
+              <CellValue
+                binding={
+                  type === 'report'
+                    ? reportBudget.totalBudgetedExpense
+                    : rolloverBudget.totalBudgeted
+                }
+                type="financial"
                 style={{
-                  flexBasis: 90,
-                  width: 90,
-                  justifyContent: 'center',
-                  alignItems: 'flex-end',
+                  ...styles.smallText,
+                  color: theme.buttonNormalText,
+                  textAlign: 'right',
+                  fontWeight: '500',
+                }}
+                formatter={value => {
+                  return format(-parseFloat(value || '0'), 'financial');
                 }}
-              >
-                <Label
-                  title="BUDGETED"
-                  style={{ color: theme.buttonNormalText }}
-                />
-                <CellValue
-                  binding={
-                    type === 'report'
-                      ? reportBudget.totalBudgetedExpense
-                      : rolloverBudget.totalBudgeted
-                  }
-                  type="financial"
-                  style={{
-                    ...styles.smallText,
-                    color: theme.buttonNormalText,
-                    textAlign: 'right',
-                    fontWeight: '500',
-                  }}
-                  formatter={value => {
-                    return format(-parseFloat(value || '0'), 'financial');
-                  }}
-                />
-              </View>
-            </Button>
-          )}
-          {(show3Cols || showSpentColumn) && (
-            <Button
-              type="bare"
-              disabled={show3Cols}
-              onClick={toggleDisplay}
+              />
+            </View>
+          </Button>
+        )}
+        {(show3Cols || showSpentColumn) && (
+          <Button
+            type="bare"
+            disabled={show3Cols}
+            onClick={toggleDisplay}
+            style={{
+              ...buttonStyle,
+              background:
+                showSpentColumn && !show3Cols
+                  ? `linear-gradient(45deg, ${theme.formInputBackgroundSelection} 8px, transparent 0)`
+                  : null,
+            }}
+          >
+            <View
               style={{
-                ...buttonStyle,
-                background:
-                  showSpentColumn && !show3Cols
-                    ? `linear-gradient(45deg, ${theme.formInputBackgroundSelection} 8px, transparent 0)`
-                    : null,
+                width: 90,
+                justifyContent: 'center',
+                alignItems: 'flex-end',
               }}
             >
-              <View
+              <Label title="SPENT" style={{ color: theme.formInputText }} />
+              <CellValue
+                binding={
+                  type === 'report'
+                    ? reportBudget.totalSpent
+                    : rolloverBudget.totalSpent
+                }
+                type="financial"
                 style={{
-                  width: 90,
-                  justifyContent: 'center',
-                  alignItems: 'flex-end',
+                  ...styles.smallText,
+                  color: theme.formInputText,
+                  textAlign: 'right',
+                  fontWeight: '500',
                 }}
-              >
-                <Label title="SPENT" style={{ color: theme.formInputText }} />
-                <CellValue
-                  binding={
-                    type === 'report'
-                      ? reportBudget.totalSpent
-                      : rolloverBudget.totalSpent
-                  }
-                  type="financial"
-                  style={{
-                    ...styles.smallText,
-                    color: theme.formInputText,
-                    textAlign: 'right',
-                    fontWeight: '500',
-                  }}
-                />
-              </View>
-            </Button>
-          )}
+              />
+            </View>
+          </Button>
+        )}
+        <View
+          style={{
+            width: 90,
+            justifyContent: 'center',
+            alignItems: 'flex-end',
+          }}
+        >
+          <Label title="BALANCE" style={{ color: theme.formInputText }} />
+          <CellValue
+            binding={
+              type === 'report'
+                ? reportBudget.totalLeftover
+                : rolloverBudget.totalBalance
+            }
+            type="financial"
+            style={{
+              ...styles.smallText,
+              color: theme.formInputText,
+              textAlign: 'right',
+              fontWeight: '500',
+            }}
+          />
+        </View>
+      </View>
+      <PullToRefresh onRefresh={onRefresh}>
+        {!editMode ? (
+          // <ScrollView
+          //   ref={el => (this.list = el)}
+          //   keyboardShouldPersistTaps="always"
+          //   refreshControl={refreshControl}
+          //   style={{ backgroundColor: colors.n10 }}
+          //   automaticallyAdjustContentInsets={false}
+          // >
           <View
+            data-testid="budget-table"
             style={{
-              width: 90,
-              justifyContent: 'center',
-              alignItems: 'flex-end',
+              paddingBottom: MOBILE_NAV_HEIGHT,
             }}
           >
-            <Label title="BALANCE" style={{ color: theme.formInputText }} />
-            <CellValue
-              binding={
-                type === 'report'
-                  ? reportBudget.totalLeftover
-                  : rolloverBudget.totalBalance
-              }
-              type="financial"
-              style={{
-                ...styles.smallText,
-                color: theme.formInputText,
-                textAlign: 'right',
-                fontWeight: '500',
-              }}
+            <BudgetGroups
+              type={type}
+              categoryGroups={categoryGroups}
+              showBudgetedCol={!showSpentColumn}
+              show3Cols={show3Cols}
+              showHiddenCategories={showHiddenCategories}
+              // gestures={gestures}
+              month={month}
+              editMode={editMode}
+              onEditGroup={onEditGroup}
+              onEditCategory={onEditCategory}
+              onSaveCategory={onSaveCategory}
+              onDeleteCategory={onDeleteCategory}
+              onAddCategory={onAddCategory}
+              onAddGroup={onAddGroup}
+              onSaveGroup={onSaveGroup}
+              onDeleteGroup={onDeleteGroup}
+              onReorderCategory={onReorderCategory}
+              onReorderGroup={onReorderGroup}
+              onOpenMonthActionMenu={onOpenMonthActionMenu}
+              onBudgetAction={onBudgetAction}
+            />
+          </View>
+        ) : (
+          // </ScrollView>
+          // <DragDrop>
+          //   {({
+          //     dragging,
+          //     onGestureEvent,
+          //     onHandlerStateChange,
+          //     scrollRef,
+          //     onScroll
+          //   }) => (
+          <View data-testid="budget-table">
+            <BudgetGroups
+              type={type}
+              categoryGroups={categoryGroups}
+              showBudgetedCol={!showSpentColumn}
+              show3Cols={show3Cols}
+              showHiddenCategories={showHiddenCategories}
+              // gestures={gestures}
+              editMode={editMode}
+              onEditGroup={onEditGroup}
+              onEditCategory={onEditCategory}
+              onSaveCategory={onSaveCategory}
+              onDeleteCategory={onDeleteCategory}
+              onAddCategory={onAddCategory}
+              onAddGroup={onAddGroup}
+              onSaveGroup={onSaveGroup}
+              onDeleteGroup={onDeleteGroup}
+              onReorderCategory={onReorderCategory}
+              onReorderGroup={onReorderGroup}
+              onOpenMonthActionMenu={onOpenMonthActionMenu}
+              onBudgetAction={onBudgetAction}
             />
           </View>
-        </View>
-        <PullToRefresh onRefresh={onRefresh}>
-          {!editMode ? (
-            // <ScrollView
-            //   ref={el => (this.list = el)}
-            //   keyboardShouldPersistTaps="always"
-            //   refreshControl={refreshControl}
-            //   style={{ backgroundColor: colors.n10 }}
-            //   automaticallyAdjustContentInsets={false}
-            // >
-            <View
-              data-testid="budget-table"
-              style={{
-                paddingBottom: MOBILE_NAV_HEIGHT,
-              }}
-            >
-              <BudgetGroups
-                type={type}
-                categoryGroups={categoryGroups}
-                showBudgetedCol={!showSpentColumn}
-                show3Cols={show3Cols}
-                showHiddenCategories={showHiddenCategories}
-                // gestures={gestures}
-                month={month}
-                editMode={editMode}
-                onEditGroup={onEditGroup}
-                onEditCategory={onEditCategory}
-                onSaveCategory={onSaveCategory}
-                onDeleteCategory={onDeleteCategory}
-                onAddCategory={onAddCategory}
-                onAddGroup={onAddGroup}
-                onSaveGroup={onSaveGroup}
-                onDeleteGroup={onDeleteGroup}
-                onReorderCategory={onReorderCategory}
-                onReorderGroup={onReorderGroup}
-                onOpenMonthActionMenu={onOpenMonthActionMenu}
-                onBudgetAction={onBudgetAction}
-              />
-            </View>
-          ) : (
-            // </ScrollView>
-            // <DragDrop>
-            //   {({
-            //     dragging,
-            //     onGestureEvent,
-            //     onHandlerStateChange,
-            //     scrollRef,
-            //     onScroll
-            //   }) => (
-            <View data-testid="budget-table">
-              <BudgetGroups
-                type={type}
-                categoryGroups={categoryGroups}
-                showBudgetedCol={!showSpentColumn}
-                show3Cols={show3Cols}
-                showHiddenCategories={showHiddenCategories}
-                // gestures={gestures}
-                editMode={editMode}
-                onEditGroup={onEditGroup}
-                onEditCategory={onEditCategory}
-                onSaveCategory={onSaveCategory}
-                onDeleteCategory={onDeleteCategory}
-                onAddCategory={onAddCategory}
-                onAddGroup={onAddGroup}
-                onSaveGroup={onSaveGroup}
-                onDeleteGroup={onDeleteGroup}
-                onReorderCategory={onReorderCategory}
-                onReorderGroup={onReorderGroup}
-                onOpenMonthActionMenu={onOpenMonthActionMenu}
-                onBudgetAction={onBudgetAction}
-              />
-            </View>
 
-            // <DragDropHighlight />
-            // </DragDrop>
-          )}
-        </PullToRefresh>
-      </Page>
-    </NamespaceContext.Provider>
+          // <DragDropHighlight />
+          // </DragDrop>
+        )}
+      </PullToRefresh>
+    </Page>
   );
 }
 
diff --git a/packages/desktop-client/src/components/mobile/budget/index.tsx b/packages/desktop-client/src/components/mobile/budget/index.tsx
index d221f00a50c8998c1eb41a3082d927774deb1b91..eb5e5a7fd377efc4fb5ec11c9422370e5098aafa 100644
--- a/packages/desktop-client/src/components/mobile/budget/index.tsx
+++ b/packages/desktop-client/src/components/mobile/budget/index.tsx
@@ -33,6 +33,7 @@ import { AnimatedLoading } from '../../../icons/AnimatedLoading';
 import { theme } from '../../../style';
 import { prewarmMonth, switchBudgetType } from '../../budget/util';
 import { View } from '../../common/View';
+import { NamespaceContext } from '../../spreadsheet/NamespaceContext';
 import { SyncRefresh } from '../../SyncRefresh';
 
 import { BudgetTable } from './BudgetTable';
@@ -369,42 +370,44 @@ function BudgetInner(props: BudgetInnerProps) {
   }
 
   return (
-    <SyncRefresh
-      onSync={async () => {
-        dispatch(sync());
-      }}
-    >
-      {({ onRefresh }) => (
-        <BudgetTable
-          // This key forces the whole table rerender when the number
-          // format changes
-          key={`${numberFormat}${hideFraction}`}
-          categoryGroups={categoryGroups}
-          type={budgetType}
-          month={currentMonth}
-          monthBounds={bounds}
-          editMode={editMode}
-          onEditMode={flag => setEditMode(flag)}
-          onShowBudgetSummary={onShowBudgetSummary}
-          onPrevMonth={onPrevMonth}
-          onNextMonth={onNextMonth}
-          onSaveGroup={onSaveGroup}
-          onDeleteGroup={onDeleteGroup}
-          onAddGroup={onAddGroup}
-          onAddCategory={onAddCategory}
-          onSaveCategory={onSaveCategory}
-          onDeleteCategory={onDeleteCategory}
-          onReorderCategory={onReorderCategory}
-          onReorderGroup={onReorderGroup}
-          onOpenMonthActionMenu={() => {}} //onOpenMonthActionMenu}
-          onBudgetAction={onBudgetAction}
-          onRefresh={onRefresh}
-          onSwitchBudgetType={onSwitchBudgetType}
-          onEditGroup={onEditGroup}
-          onEditCategory={onEditCategory}
-        />
-      )}
-    </SyncRefresh>
+    <NamespaceContext.Provider value={monthUtils.sheetForMonth(currentMonth)}>
+      <SyncRefresh
+        onSync={async () => {
+          dispatch(sync());
+        }}
+      >
+        {({ onRefresh }) => (
+          <BudgetTable
+            // This key forces the whole table rerender when the number
+            // format changes
+            key={`${numberFormat}${hideFraction}`}
+            categoryGroups={categoryGroups}
+            type={budgetType}
+            month={currentMonth}
+            monthBounds={bounds}
+            editMode={editMode}
+            onEditMode={flag => setEditMode(flag)}
+            onShowBudgetSummary={onShowBudgetSummary}
+            onPrevMonth={onPrevMonth}
+            onNextMonth={onNextMonth}
+            onSaveGroup={onSaveGroup}
+            onDeleteGroup={onDeleteGroup}
+            onAddGroup={onAddGroup}
+            onAddCategory={onAddCategory}
+            onSaveCategory={onSaveCategory}
+            onDeleteCategory={onDeleteCategory}
+            onReorderCategory={onReorderCategory}
+            onReorderGroup={onReorderGroup}
+            onOpenMonthActionMenu={() => {}} //onOpenMonthActionMenu}
+            onBudgetAction={onBudgetAction}
+            onRefresh={onRefresh}
+            onSwitchBudgetType={onSwitchBudgetType}
+            onEditGroup={onEditGroup}
+            onEditCategory={onEditCategory}
+          />
+        )}
+      </SyncRefresh>
+    </NamespaceContext.Provider>
   );
 }
 
diff --git a/packages/desktop-client/src/components/mobile/transactions/TransactionEdit.jsx b/packages/desktop-client/src/components/mobile/transactions/TransactionEdit.jsx
index 9e9be907aa153f0fa5676b65c5e1736b84707acd..98b02cd0e9e96ade3870418dcfd34b1ce9e3af9d 100644
--- a/packages/desktop-client/src/components/mobile/transactions/TransactionEdit.jsx
+++ b/packages/desktop-client/src/components/mobile/transactions/TransactionEdit.jsx
@@ -428,6 +428,7 @@ const TransactionEditInner = memo(function TransactionEditInner({
       [],
     [unserializedTransactions, dateFormat],
   );
+  const { grouped: categoryGroups } = useCategories();
 
   const [transaction, ...childTransactions] = transactions;
 
@@ -542,24 +543,90 @@ const TransactionEditInner = memo(function TransactionEditInner({
   };
 
   const onClick = (transactionId, name) => {
-    onRequestActiveEdit?.(getFieldName(transaction.id, 'payee'), () => {
-      dispatch(
-        pushModal('edit-field', {
-          name,
-          onSubmit: (name, value) => {
-            const transaction = unserializedTransactions.find(
-              t => t.id === transactionId,
-            );
-            // This is a deficiency of this API, need to fix. It
-            // assumes that it receives a serialized transaction,
-            // but we only have access to the raw transaction
-            onEdit(serializeTransaction(transaction, dateFormat), name, value);
-          },
-          onClose: () => {
-            onClearActiveEdit();
-          },
-        }),
+    onRequestActiveEdit?.(getFieldName(transaction.id, name), () => {
+      const transaction = unserializedTransactions.find(
+        t => t.id === transactionId,
       );
+      switch (name) {
+        case 'category':
+          dispatch(
+            pushModal('category-autocomplete', {
+              categoryGroups,
+              onSelect: categoryId => {
+                // This is a deficiency of this API, need to fix. It
+                // assumes that it receives a serialized transaction,
+                // but we only have access to the raw transaction
+                onEdit(
+                  serializeTransaction(transaction, dateFormat),
+                  name,
+                  categoryId,
+                );
+              },
+              onClose: () => {
+                onClearActiveEdit();
+              },
+            }),
+          );
+          break;
+        case 'account':
+          dispatch(
+            pushModal('account-autocomplete', {
+              onSelect: accountId => {
+                // This is a deficiency of this API, need to fix. It
+                // assumes that it receives a serialized transaction,
+                // but we only have access to the raw transaction
+                onEdit(
+                  serializeTransaction(transaction, dateFormat),
+                  name,
+                  accountId,
+                );
+              },
+              onClose: () => {
+                onClearActiveEdit();
+              },
+            }),
+          );
+          break;
+        case 'payee':
+          dispatch(
+            pushModal('payee-autocomplete', {
+              onSelect: payeeId => {
+                // This is a deficiency of this API, need to fix. It
+                // assumes that it receives a serialized transaction,
+                // but we only have access to the raw transaction
+                onEdit(
+                  serializeTransaction(transaction, dateFormat),
+                  name,
+                  payeeId,
+                );
+              },
+              onClose: () => {
+                onClearActiveEdit();
+              },
+            }),
+          );
+          break;
+        default:
+          dispatch(
+            pushModal('edit-field', {
+              name,
+              onSubmit: (name, value) => {
+                // This is a deficiency of this API, need to fix. It
+                // assumes that it receives a serialized transaction,
+                // but we only have access to the raw transaction
+                onEdit(
+                  serializeTransaction(transaction, dateFormat),
+                  name,
+                  value,
+                );
+              },
+              onClose: () => {
+                onClearActiveEdit();
+              },
+            }),
+          );
+          break;
+      }
     });
   };
 
diff --git a/packages/desktop-client/src/components/modals/AccountAutocompleteModal.tsx b/packages/desktop-client/src/components/modals/AccountAutocompleteModal.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..5ec7911bef17da12c446f3f6a642fdc46e962fa2
--- /dev/null
+++ b/packages/desktop-client/src/components/modals/AccountAutocompleteModal.tsx
@@ -0,0 +1,78 @@
+import React, { type ComponentPropsWithoutRef } from 'react';
+
+import { useResponsive } from '../../ResponsiveProvider';
+import { theme } from '../../style';
+import { AccountAutocomplete } from '../autocomplete/AccountAutocomplete';
+import { Modal } from '../common/Modal';
+import { View } from '../common/View';
+import { SectionLabel } from '../forms';
+import { type CommonModalProps } from '../Modals';
+
+type AccountAutocompleteModalProps = {
+  modalProps: CommonModalProps;
+  autocompleteProps: ComponentPropsWithoutRef<typeof AccountAutocomplete>;
+  onClose: () => void;
+};
+
+export function AccountAutocompleteModal({
+  modalProps,
+  autocompleteProps,
+  onClose,
+}: AccountAutocompleteModalProps) {
+  const _onClose = () => {
+    modalProps.onClose();
+    onClose?.();
+  };
+
+  const { isNarrowWidth } = useResponsive();
+  const defaultAutocompleteProps = {
+    containerProps: { style: { height: isNarrowWidth ? '90vh' : 275 } },
+  };
+
+  return (
+    <Modal
+      title="Account"
+      noAnimation={!isNarrowWidth}
+      showHeader={isNarrowWidth}
+      focusAfterClose={false}
+      {...modalProps}
+      onClose={_onClose}
+      padding={0}
+      style={{
+        flex: 0,
+        height: isNarrowWidth ? '85vh' : 275,
+        padding: '15px 10px',
+        borderRadius: '6px',
+        ...(!isNarrowWidth && {
+          backgroundColor: theme.mobileModalBackground,
+          color: theme.mobileModalText,
+        }),
+      }}
+    >
+      {() => (
+        <View>
+          {!isNarrowWidth && (
+            <SectionLabel
+              title="Account"
+              style={{
+                alignSelf: 'center',
+                color: theme.mobileModalText,
+                marginBottom: 10,
+              }}
+            />
+          )}
+          <View style={{ flex: 1 }}>
+            <AccountAutocomplete
+              focused={true}
+              embedded={true}
+              closeOnBlur={false}
+              onClose={_onClose}
+              {...defaultAutocompleteProps}
+              {...autocompleteProps}
+            />
+          </View>
+        </View>
+      )}
+    </Modal>
+  );
+}
diff --git a/packages/desktop-client/src/components/modals/AccountMenuModal.tsx b/packages/desktop-client/src/components/modals/AccountMenuModal.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..c67599891926ce5b51d272c449ba6fc24e061087
--- /dev/null
+++ b/packages/desktop-client/src/components/modals/AccountMenuModal.tsx
@@ -0,0 +1,250 @@
+import React, { useState } from 'react';
+
+import { useLiveQuery } from 'loot-core/src/client/query-hooks';
+import { q } from 'loot-core/src/shared/query';
+import { type AccountEntity } from 'loot-core/types/models';
+
+import { useAccounts } from '../../hooks/useAccounts';
+import { SvgClose, SvgDotsHorizontalTriple, SvgLockOpen } from '../../icons/v1';
+import { SvgNotesPaper } from '../../icons/v2';
+import { type CSSProperties, styles, theme } from '../../style';
+import { Button } from '../common/Button';
+import { Menu } from '../common/Menu';
+import { Modal } from '../common/Modal';
+import { View } from '../common/View';
+import { type CommonModalProps } from '../Modals';
+import { Notes } from '../Notes';
+import { Tooltip } from '../tooltips';
+
+type NoteEntity = {
+  id: string;
+  note: string;
+};
+
+type AccountMenuModalProps = {
+  modalProps: CommonModalProps;
+  accountId: string;
+  onSave: (account: AccountEntity) => void;
+  onCloseAccount: (accountId: string) => void;
+  onReopenAccount: (accountId: string) => void;
+  onEditNotes: (id: string) => void;
+  onClose?: () => void;
+};
+
+export function AccountMenuModal({
+  modalProps,
+  accountId,
+  onSave,
+  onCloseAccount,
+  onReopenAccount,
+  onEditNotes,
+  onClose,
+}: AccountMenuModalProps) {
+  const accounts = useAccounts();
+  const account = accounts.find(c => c.id === accountId);
+  const data = useLiveQuery(
+    () => q('notes').filter({ id: account?.id }).select('*'),
+    [account?.id],
+  ) as NoteEntity[] | null;
+  const originalNotes = data && data.length > 0 ? data[0].note : null;
+
+  const _onClose = () => {
+    modalProps?.onClose();
+    onClose?.();
+  };
+
+  const onRename = (newName: string) => {
+    if (!account) {
+      return;
+    }
+
+    if (newName !== account.name) {
+      onSave?.({
+        ...account,
+        name: newName,
+      });
+    }
+  };
+
+  const _onEditNotes = () => {
+    if (!account) {
+      return;
+    }
+
+    onEditNotes?.(account.id);
+  };
+
+  const buttonStyle: CSSProperties = {
+    ...styles.mediumText,
+    height: styles.mobileMinHeight,
+    color: theme.formLabelText,
+    // Adjust based on desired number of buttons per row.
+    flexBasis: '100%',
+  };
+
+  if (!account) {
+    return null;
+  }
+
+  return (
+    <Modal
+      title={account.name}
+      titleStyle={styles.underlinedText}
+      showHeader
+      focusAfterClose={false}
+      {...modalProps}
+      onClose={_onClose}
+      padding={0}
+      style={{
+        flex: 1,
+        height: '45vh',
+        padding: '0 10px',
+        borderRadius: '6px',
+      }}
+      editableTitle={true}
+      onTitleUpdate={onRename}
+      leftHeaderContent={
+        <AdditionalAccountMenu
+          account={account}
+          onClose={onCloseAccount}
+          onReopen={onReopenAccount}
+        />
+      }
+    >
+      {({ isEditingTitle }) => (
+        <View
+          style={{
+            flex: 1,
+            flexDirection: 'column',
+          }}
+        >
+          <View
+            style={{
+              overflowY: 'auto',
+              flex: 1,
+            }}
+          >
+            <Notes
+              notes={
+                originalNotes && originalNotes.length > 0
+                  ? originalNotes
+                  : 'No notes'
+              }
+              editable={false}
+              focused={false}
+              getStyle={() => ({
+                borderRadius: 6,
+                ...((!originalNotes || originalNotes.length === 0) && {
+                  justifySelf: 'center',
+                  alignSelf: 'center',
+                  color: theme.pageTextSubdued,
+                }),
+              })}
+            />
+          </View>
+          <View
+            style={{
+              flexDirection: 'row',
+              flexWrap: 'wrap',
+              justifyContent: 'space-between',
+              alignContent: 'space-between',
+              margin: '10px 0',
+            }}
+          >
+            <Button
+              style={{
+                ...buttonStyle,
+                display: isEditingTitle ? 'none' : undefined,
+              }}
+              onClick={_onEditNotes}
+            >
+              <SvgNotesPaper
+                width={20}
+                height={20}
+                style={{ paddingRight: 5 }}
+              />
+              Edit notes
+            </Button>
+          </View>
+        </View>
+      )}
+    </Modal>
+  );
+}
+
+type AdditionalAccountMenuProps = {
+  account: AccountEntity;
+  onClose?: (accountId: string) => void;
+  onReopen?: (accountId: string) => void;
+};
+
+function AdditionalAccountMenu({
+  account,
+  onClose,
+  onReopen,
+}: AdditionalAccountMenuProps) {
+  const [menuOpen, setMenuOpen] = useState(false);
+  const itemStyle: CSSProperties = {
+    ...styles.mediumText,
+    height: styles.mobileMinHeight,
+  };
+
+  return (
+    <View>
+      <Button
+        type="bare"
+        aria-label="Menu"
+        onClick={() => {
+          setMenuOpen(true);
+        }}
+      >
+        <SvgDotsHorizontalTriple
+          width={17}
+          height={17}
+          style={{ color: 'currentColor' }}
+        />
+        {menuOpen && (
+          <Tooltip
+            position="bottom-left"
+            style={{ padding: 0 }}
+            onClose={() => {
+              setMenuOpen(false);
+            }}
+          >
+            <Menu
+              getItemStyle={() => itemStyle}
+              items={[
+                account.closed
+                  ? {
+                      name: 'reopen',
+                      text: 'Reopen account',
+                      icon: SvgLockOpen,
+                      iconSize: 15,
+                    }
+                  : {
+                      name: 'close',
+                      text: 'Close account',
+                      icon: SvgClose,
+                      iconSize: 15,
+                    },
+              ]}
+              onMenuSelect={name => {
+                setMenuOpen(false);
+                switch (name) {
+                  case 'close':
+                    onClose?.(account.id);
+                    break;
+                  case 'reopen':
+                    onReopen?.(account.id);
+                    break;
+                  default:
+                    throw new Error(`Unrecognized menu option: ${name}`);
+                }
+              }}
+            />
+          </Tooltip>
+        )}
+      </Button>
+    </View>
+  );
+}
diff --git a/packages/desktop-client/src/components/modals/CategoryAutocompleteModal.tsx b/packages/desktop-client/src/components/modals/CategoryAutocompleteModal.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..6d5c9f9722fac4106373a278aceb70271f141bcc
--- /dev/null
+++ b/packages/desktop-client/src/components/modals/CategoryAutocompleteModal.tsx
@@ -0,0 +1,80 @@
+import React, { type ComponentPropsWithoutRef } from 'react';
+
+import { useResponsive } from '../../ResponsiveProvider';
+import { theme } from '../../style';
+import { CategoryAutocomplete } from '../autocomplete/CategoryAutocomplete';
+import { Modal } from '../common/Modal';
+import { View } from '../common/View';
+import { SectionLabel } from '../forms';
+import { type CommonModalProps } from '../Modals';
+
+type CategoryAutocompleteModalProps = {
+  modalProps: CommonModalProps;
+  autocompleteProps: ComponentPropsWithoutRef<typeof CategoryAutocomplete>;
+  onClose: () => void;
+};
+
+export function CategoryAutocompleteModal({
+  modalProps,
+  autocompleteProps,
+  onClose,
+}: CategoryAutocompleteModalProps) {
+  const _onClose = () => {
+    modalProps.onClose();
+    onClose?.();
+  };
+
+  const { isNarrowWidth } = useResponsive();
+
+  const defaultAutocompleteProps = {
+    containerProps: { style: { height: isNarrowWidth ? '90vh' : 275 } },
+  };
+
+  return (
+    <Modal
+      title="Category"
+      noAnimation={!isNarrowWidth}
+      showHeader={isNarrowWidth}
+      focusAfterClose={false}
+      {...modalProps}
+      onClose={_onClose}
+      padding={0}
+      style={{
+        flex: 0,
+        height: isNarrowWidth ? '85vh' : 275,
+        padding: '15px 10px',
+        borderRadius: '6px',
+        ...(!isNarrowWidth && {
+          backgroundColor: theme.mobileModalBackground,
+          color: theme.mobileModalText,
+        }),
+      }}
+    >
+      {() => (
+        <View>
+          {!isNarrowWidth && (
+            <SectionLabel
+              title="Category"
+              style={{
+                alignSelf: 'center',
+                color: theme.mobileModalText,
+                marginBottom: 10,
+              }}
+            />
+          )}
+          <View style={{ flex: 1 }}>
+            <CategoryAutocomplete
+              focused={true}
+              embedded={true}
+              closeOnBlur={false}
+              showSplitOption={false}
+              onClose={_onClose}
+              {...defaultAutocompleteProps}
+              {...autocompleteProps}
+            />
+          </View>
+        </View>
+      )}
+    </Modal>
+  );
+}
diff --git a/packages/desktop-client/src/components/modals/CategoryGroupMenu.tsx b/packages/desktop-client/src/components/modals/CategoryGroupMenuModal.tsx
similarity index 92%
rename from packages/desktop-client/src/components/modals/CategoryGroupMenu.tsx
rename to packages/desktop-client/src/components/modals/CategoryGroupMenuModal.tsx
index 42e24a0b80980a0e68ce3b9a643667ddc509d019..c963e668fb8a13dc3f75e2ba87ce6ec640f230cc 100644
--- a/packages/desktop-client/src/components/modals/CategoryGroupMenu.tsx
+++ b/packages/desktop-client/src/components/modals/CategoryGroupMenuModal.tsx
@@ -17,9 +17,7 @@ import { type CommonModalProps } from '../Modals';
 import { Notes } from '../Notes';
 import { Tooltip } from '../tooltips';
 
-const BUTTON_HEIGHT = 40;
-
-type CategoryGroupMenuProps = {
+type CategoryGroupMenuModalProps = {
   modalProps: CommonModalProps;
   groupId: string;
   onSave: (group: CategoryGroupEntity) => void;
@@ -30,7 +28,7 @@ type CategoryGroupMenuProps = {
   onClose?: () => void;
 };
 
-export function CategoryGroupMenu({
+export function CategoryGroupMenuModal({
   modalProps,
   groupId,
   onSave,
@@ -38,7 +36,7 @@ export function CategoryGroupMenu({
   onEditNotes,
   onDelete,
   onClose,
-}: CategoryGroupMenuProps) {
+}: CategoryGroupMenuModalProps) {
   const { grouped: categoryGroups } = useCategories();
   const group = categoryGroups.find(g => g.id === groupId);
   const data = useLiveQuery(
@@ -47,47 +45,43 @@ export function CategoryGroupMenu({
   );
   const notes = data && data.length > 0 ? data[0].note : null;
 
-  function _onClose() {
+  const _onClose = () => {
     modalProps?.onClose();
     onClose?.();
-  }
+  };
 
-  function _onRename(newName) {
+  const onRename = newName => {
     if (newName !== group.name) {
       onSave?.({
         ...group,
         name: newName,
       });
     }
-  }
+  };
 
-  function _onAddCategory() {
+  const _onAddCategory = () => {
     onAddCategory?.(group.id, group.is_income);
-  }
+  };
 
-  function _onEditNotes() {
+  const _onEditNotes = () => {
     onEditNotes?.(group.id);
-  }
+  };
 
-  function _onToggleVisibility() {
+  const _onToggleVisibility = () => {
     onSave?.({
       ...group,
       hidden: !!!group.hidden,
     });
     _onClose();
-  }
+  };
 
-  function _onDelete() {
+  const _onDelete = () => {
     onDelete?.(group.id);
-  }
-
-  function onNameUpdate(newName) {
-    _onRename(newName);
-  }
+  };
 
   const buttonStyle: CSSProperties = {
     ...styles.mediumText,
-    height: BUTTON_HEIGHT,
+    height: styles.mobileMinHeight,
     color: theme.formLabelText,
     // Adjust based on desired number of buttons per row.
     flexBasis: '48%',
@@ -111,7 +105,7 @@ export function CategoryGroupMenu({
       }}
       editableTitle={true}
       titleStyle={styles.underlinedText}
-      onTitleUpdate={onNameUpdate}
+      onTitleUpdate={onRename}
       leftHeaderContent={
         <AdditionalCategoryGroupMenu
           group={group}
@@ -194,7 +188,7 @@ function AdditionalCategoryGroupMenu({ group, onDelete, onToggleVisibility }) {
   const [menuOpen, setMenuOpen] = useState(false);
   const itemStyle: CSSProperties = {
     ...styles.mediumText,
-    height: BUTTON_HEIGHT,
+    height: styles.mobileMinHeight,
   };
 
   return (
@@ -224,6 +218,7 @@ function AdditionalCategoryGroupMenu({ group, onDelete, onToggleVisibility }) {
                 ...styles.mediumText,
                 color: theme.formLabelText,
               }}
+              getItemStyle={() => itemStyle}
               items={
                 [
                   {
@@ -231,7 +226,6 @@ function AdditionalCategoryGroupMenu({ group, onDelete, onToggleVisibility }) {
                     text: group.hidden ? 'Show' : 'Hide',
                     icon: group.hidden ? SvgViewShow : SvgViewHide,
                     iconSize: 16,
-                    style: itemStyle,
                   },
                   ...(!group.is_income && [
                     Menu.line,
@@ -240,7 +234,6 @@ function AdditionalCategoryGroupMenu({ group, onDelete, onToggleVisibility }) {
                       text: 'Delete',
                       icon: SvgTrash,
                       iconSize: 15,
-                      style: itemStyle,
                     },
                   ]),
                 ].filter(i => i != null) as ComponentProps<typeof Menu>['items']
diff --git a/packages/desktop-client/src/components/modals/CategoryMenu.tsx b/packages/desktop-client/src/components/modals/CategoryMenuModal.tsx
similarity index 91%
rename from packages/desktop-client/src/components/modals/CategoryMenu.tsx
rename to packages/desktop-client/src/components/modals/CategoryMenuModal.tsx
index 5d2c704f88ab49ae3c4469d19aca6b8b80889bef..a67c1188957223d5950dc4becdf7607ac1d1d408 100644
--- a/packages/desktop-client/src/components/modals/CategoryMenu.tsx
+++ b/packages/desktop-client/src/components/modals/CategoryMenuModal.tsx
@@ -17,9 +17,7 @@ import { type CommonModalProps } from '../Modals';
 import { Notes } from '../Notes';
 import { Tooltip } from '../tooltips';
 
-const BUTTON_HEIGHT = 40;
-
-type CategoryMenuProps = {
+type CategoryMenuModalProps = {
   modalProps: CommonModalProps;
   categoryId: string;
   onSave: (category: CategoryEntity) => void;
@@ -28,14 +26,14 @@ type CategoryMenuProps = {
   onClose?: () => void;
 };
 
-export function CategoryMenu({
+export function CategoryMenuModal({
   modalProps,
   categoryId,
   onSave,
   onEditNotes,
   onDelete,
   onClose,
-}: CategoryMenuProps) {
+}: CategoryMenuModalProps) {
   const { list: categories } = useCategories();
   const category = categories.find(c => c.id === categoryId);
   const data = useLiveQuery(
@@ -44,43 +42,39 @@ export function CategoryMenu({
   );
   const originalNotes = data && data.length > 0 ? data[0].note : null;
 
-  function _onClose() {
+  const _onClose = () => {
     modalProps?.onClose();
     onClose?.();
-  }
+  };
 
-  function _onRename(newName) {
+  const onRename = newName => {
     if (newName !== category.name) {
       onSave?.({
         ...category,
         name: newName,
       });
     }
-  }
+  };
 
-  function _onToggleVisibility() {
+  const _onToggleVisibility = () => {
     onSave?.({
       ...category,
       hidden: !category.hidden,
     });
     _onClose();
-  }
+  };
 
-  function _onEditNotes() {
+  const _onEditNotes = () => {
     onEditNotes?.(category.id);
-  }
+  };
 
-  function _onDelete() {
+  const _onDelete = () => {
     onDelete?.(category.id);
-  }
-
-  function onNameUpdate(newName) {
-    _onRename(newName);
-  }
+  };
 
   const buttonStyle: CSSProperties = {
     ...styles.mediumText,
-    height: BUTTON_HEIGHT,
+    height: styles.mobileMinHeight,
     color: theme.formLabelText,
     // Adjust based on desired number of buttons per row.
     flexBasis: '100%',
@@ -102,7 +96,7 @@ export function CategoryMenu({
         borderRadius: '6px',
       }}
       editableTitle={true}
-      onTitleUpdate={onNameUpdate}
+      onTitleUpdate={onRename}
       leftHeaderContent={
         <AdditionalCategoryMenu
           category={category}
@@ -172,7 +166,7 @@ function AdditionalCategoryMenu({ category, onDelete, onToggleVisibility }) {
   const [menuOpen, setMenuOpen] = useState(false);
   const itemStyle: CSSProperties = {
     ...styles.mediumText,
-    height: BUTTON_HEIGHT,
+    height: styles.mobileMinHeight,
   };
 
   return (
@@ -198,13 +192,13 @@ function AdditionalCategoryMenu({ category, onDelete, onToggleVisibility }) {
             }}
           >
             <Menu
+              getItemStyle={() => itemStyle}
               items={[
                 {
                   name: 'toggleVisibility',
                   text: category.hidden ? 'Show' : 'Hide',
                   icon: category.hidden ? SvgViewShow : SvgViewHide,
                   iconSize: 16,
-                  style: itemStyle,
                 },
                 Menu.line,
                 {
@@ -212,7 +206,6 @@ function AdditionalCategoryMenu({ category, onDelete, onToggleVisibility }) {
                   text: 'Delete',
                   icon: SvgTrash,
                   iconSize: 15,
-                  style: itemStyle,
                 },
               ]}
               onMenuSelect={itemName => {
diff --git a/packages/desktop-client/src/components/modals/CloseAccount.tsx b/packages/desktop-client/src/components/modals/CloseAccountModal.tsx
similarity index 57%
rename from packages/desktop-client/src/components/modals/CloseAccount.tsx
rename to packages/desktop-client/src/components/modals/CloseAccountModal.tsx
index afac51f8a1e839e69cda778be05d0b9339487233..aa71110c21ed367bb39c1fc8a0b7ade7484b845b 100644
--- a/packages/desktop-client/src/components/modals/CloseAccount.tsx
+++ b/packages/desktop-client/src/components/modals/CloseAccountModal.tsx
@@ -1,13 +1,19 @@
 // @ts-strict-ignore
 import React, { useState } from 'react';
+import { useDispatch } from 'react-redux';
 
+import {
+  closeAccount,
+  forceCloseAccount,
+  pushModal,
+} from 'loot-core/client/actions';
 import { integerToCurrency } from 'loot-core/src/shared/util';
 import { type AccountEntity } from 'loot-core/src/types/models';
 
 import { useAccounts } from '../../hooks/useAccounts';
-import { type BoundActions } from '../../hooks/useActions';
 import { useCategories } from '../../hooks/useCategories';
-import { theme } from '../../style';
+import { useResponsive } from '../../ResponsiveProvider';
+import { type CSSProperties, styles, theme } from '../../style';
 import { AccountAutocomplete } from '../autocomplete/AccountAutocomplete';
 import { CategoryAutocomplete } from '../autocomplete/CategoryAutocomplete';
 import { Button } from '../common/Button';
@@ -32,29 +38,53 @@ function needsCategory(
   return account.offbudget === 0 && isOffBudget;
 }
 
-type CloseAccountProps = {
+type CloseAccountModalProps = {
   account: AccountEntity;
   balance: number;
   canDelete: boolean;
-  actions: BoundActions;
   modalProps: CommonModalProps;
 };
 
-export function CloseAccount({
+export function CloseAccountModal({
   account,
   balance,
   canDelete,
-  actions,
   modalProps,
-}: CloseAccountProps) {
+}: CloseAccountModalProps) {
+  const accounts = useAccounts().filter(a => a.closed === 0);
+  const { grouped: categoryGroups, list: categories } = useCategories();
   const [loading, setLoading] = useState(false);
-  const [transfer, setTransfer] = useState('');
-  const [category, setCategory] = useState('');
+  const [transferAccountId, setTransferAccountId] = useState('');
+  const transferAccount = accounts.find(a => a.id === transferAccountId);
+  const [categoryId, setCategoryId] = useState('');
+  const category = categories.find(c => c.id === categoryId);
 
   const [transferError, setTransferError] = useState(false);
   const [categoryError, setCategoryError] = useState(false);
-  const accounts = useAccounts().filter(a => a.closed === 0);
-  const { grouped: categoryGroups } = useCategories();
+  const dispatch = useDispatch();
+  const { isNarrowWidth } = useResponsive();
+
+  const onSelectAccount = accId => {
+    setTransferAccountId(accId);
+    if (transferError && accId) {
+      setTransferError(false);
+    }
+  };
+
+  const onSelectCategory = catId => {
+    setCategoryId(catId);
+    if (categoryError && catId) {
+      setCategoryError(false);
+    }
+  };
+
+  const narrowStyle: CSSProperties = isNarrowWidth
+    ? {
+        userSelect: 'none',
+        height: styles.mobileMinHeight,
+        ...styles.mediumText,
+      }
+    : {};
 
   return (
     <Modal
@@ -82,21 +112,25 @@ export function CloseAccount({
             onSubmit={event => {
               event.preventDefault();
 
-              const transferError = balance !== 0 && transfer === '';
+              const transferError = balance !== 0 && transferAccountId === '';
               setTransferError(transferError);
 
               const categoryError =
-                needsCategory(account, transfer, accounts) && category === '';
+                needsCategory(account, transferAccountId, accounts) &&
+                categoryId === '';
               setCategoryError(categoryError);
 
               if (!transferError && !categoryError) {
                 setLoading(true);
 
-                actions
-                  .closeAccount(account.id, transfer || null, category || null)
-                  .then(() => {
-                    modalProps.onClose();
-                  });
+                dispatch(
+                  closeAccount(
+                    account.id,
+                    transferAccountId || null,
+                    categoryId || null,
+                  ),
+                );
+                modalProps.onClose();
               }
             }}
           >
@@ -112,16 +146,25 @@ export function CloseAccount({
                 <View style={{ marginBottom: 15 }}>
                   <AccountAutocomplete
                     includeClosedAccounts={false}
-                    value={transfer}
+                    value={transferAccountId}
                     inputProps={{
                       placeholder: 'Select account...',
+                      ...(isNarrowWidth && {
+                        value: transferAccount?.name || '',
+                        style: {
+                          ...narrowStyle,
+                        },
+                        onClick: () => {
+                          dispatch(
+                            pushModal('account-autocomplete', {
+                              includeClosedAccounts: false,
+                              onSelect: onSelectAccount,
+                            }),
+                          );
+                        },
+                      }),
                     }}
-                    onSelect={acc => {
-                      setTransfer(acc);
-                      if (transferError && acc) {
-                        setTransferError(false);
-                      }
-                    }}
+                    onSelect={onSelectAccount}
                   />
                 </View>
 
@@ -131,7 +174,7 @@ export function CloseAccount({
                   </FormError>
                 )}
 
-                {needsCategory(account, transfer, accounts) && (
+                {needsCategory(account, transferAccountId, accounts) && (
                   <View style={{ marginBottom: 15 }}>
                     <Paragraph>
                       Since you are transferring the balance from a budgeted
@@ -141,17 +184,26 @@ export function CloseAccount({
 
                     <CategoryAutocomplete
                       categoryGroups={categoryGroups}
-                      value={category}
+                      value={categoryId}
                       inputProps={{
                         placeholder: 'Select category...',
+                        ...(isNarrowWidth && {
+                          value: category?.name || '',
+                          style: {
+                            ...narrowStyle,
+                          },
+                          onClick: () => {
+                            dispatch(
+                              pushModal('category-autocomplete', {
+                                categoryGroups,
+                                showHiddenCategories: true,
+                                onSelect: onSelectCategory,
+                              }),
+                            );
+                          },
+                        }),
                       }}
-                      onSelect={newValue => {
-                        setCategory(newValue);
-                        if (categoryError && newValue) {
-                          setCategoryError(false);
-                        }
-                      }}
-                      showHiddenCategories={true}
+                      onSelect={onSelectCategory}
                     />
 
                     {categoryError && (
@@ -170,9 +222,8 @@ export function CloseAccount({
                     onClick={() => {
                       setLoading(true);
 
-                      actions
-                        .forceCloseAccount(account.id)
-                        .then(() => modalProps.onClose());
+                      dispatch(forceCloseAccount(account.id));
+                      modalProps.onClose();
                     }}
                     style={{ color: theme.errorText }}
                   >
@@ -191,10 +242,23 @@ export function CloseAccount({
                 justifyContent: 'flex-end',
               }}
             >
-              <Button style={{ marginRight: 10 }} onClick={modalProps.onClose}>
+              <Button
+                style={{
+                  marginRight: 10,
+                  height: isNarrowWidth ? styles.mobileMinHeight : undefined,
+                }}
+                onClick={modalProps.onClose}
+              >
                 Cancel
               </Button>
-              <Button type="primary">Close Account</Button>
+              <Button
+                type="primary"
+                style={{
+                  height: isNarrowWidth ? styles.mobileMinHeight : undefined,
+                }}
+              >
+                Close Account
+              </Button>
             </View>
           </form>
         </View>
diff --git a/packages/desktop-client/src/components/modals/CoverModal.tsx b/packages/desktop-client/src/components/modals/CoverModal.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..90f4369da98de628b0c3f8aa428f0fccc721263e
--- /dev/null
+++ b/packages/desktop-client/src/components/modals/CoverModal.tsx
@@ -0,0 +1,115 @@
+import React, { useCallback, useEffect, useState } from 'react';
+import { useDispatch } from 'react-redux';
+
+import { pushModal } from 'loot-core/client/actions';
+
+import { useCategories } from '../../hooks/useCategories';
+import { useInitialMount } from '../../hooks/useInitialMount';
+import { styles } from '../../style';
+import { addToBeBudgetedGroup } from '../budget/util';
+import { Button } from '../common/Button';
+import { Modal } from '../common/Modal';
+import { View } from '../common/View';
+import { FieldLabel, TapField } from '../mobile/MobileForms';
+import { type CommonModalProps } from '../Modals';
+
+type CoverModalProps = {
+  modalProps: CommonModalProps;
+  categoryId: string;
+  onSubmit: (categoryId: string) => void;
+};
+
+export function CoverModal({
+  modalProps,
+  categoryId,
+  onSubmit,
+}: CoverModalProps) {
+  const { grouped: originalCategoryGroups, list: categories } = useCategories();
+  const categoryGroups = addToBeBudgetedGroup(
+    originalCategoryGroups.filter(g => !g.is_income),
+  );
+
+  const [fromCategoryId, setFromCategoryId] = useState<string | null>(null);
+  const dispatch = useDispatch();
+
+  const onCategoryClick = useCallback(() => {
+    dispatch(
+      pushModal('category-autocomplete', {
+        categoryGroups,
+        onSelect: categoryId => {
+          setFromCategoryId(categoryId);
+        },
+      }),
+    );
+  }, [categoryGroups, dispatch]);
+
+  const _onSubmit = (categoryId: string | null) => {
+    if (categoryId) {
+      onSubmit?.(categoryId);
+    }
+
+    modalProps.onClose();
+  };
+
+  const initialMount = useInitialMount();
+
+  useEffect(() => {
+    if (initialMount) {
+      onCategoryClick();
+    }
+  }, [initialMount, onCategoryClick]);
+
+  const category = categories.find(c => c.id === categoryId);
+
+  if (!category) {
+    return null;
+  }
+
+  return (
+    <Modal
+      title={`Cover: ${category.name}`}
+      showHeader
+      focusAfterClose={false}
+      {...modalProps}
+      padding={0}
+      style={{
+        flex: 1,
+        padding: '0 10px',
+        paddingBottom: 10,
+        borderRadius: '6px',
+      }}
+    >
+      {() => (
+        <>
+          <View>
+            <FieldLabel title="Cover from category:" />
+            <TapField
+              value={categories.find(c => c.id === fromCategoryId)?.name}
+              onClick={onCategoryClick}
+            />
+          </View>
+
+          <View
+            style={{
+              justifyContent: 'center',
+              alignItems: 'center',
+              marginTop: 10,
+            }}
+          >
+            <Button
+              type="primary"
+              style={{
+                height: styles.mobileMinHeight,
+                marginLeft: styles.mobileEditingPadding,
+                marginRight: styles.mobileEditingPadding,
+              }}
+              onClick={() => _onSubmit(fromCategoryId)}
+            >
+              Transfer
+            </Button>
+          </View>
+        </>
+      )}
+    </Modal>
+  );
+}
diff --git a/packages/desktop-client/src/components/modals/EditField.jsx b/packages/desktop-client/src/components/modals/EditField.jsx
index 52f1bb7912533697ad9772533cc9d89260c0d32d..a4822faf32fbc2dfa5f1f5b624d993b46659cd18 100644
--- a/packages/desktop-client/src/components/modals/EditField.jsx
+++ b/packages/desktop-client/src/components/modals/EditField.jsx
@@ -5,28 +5,10 @@ import { parseISO, format as formatDate, parse as parseDate } from 'date-fns';
 import { currentDay, dayFromDate } from 'loot-core/src/shared/months';
 import { amountToInteger } from 'loot-core/src/shared/util';
 
-import { useAccounts } from '../../hooks/useAccounts';
-import { useActions } from '../../hooks/useActions';
 import { useCategories } from '../../hooks/useCategories';
 import { useDateFormat } from '../../hooks/useDateFormat';
-import { usePayees } from '../../hooks/usePayees';
-import { SvgAdd } from '../../icons/v1';
 import { useResponsive } from '../../ResponsiveProvider';
-import { styles, theme } from '../../style';
-import {
-  AccountAutocomplete,
-  AccountItem,
-} from '../autocomplete/AccountAutocomplete';
-import {
-  CategoryAutocomplete,
-  CategoryItem,
-} from '../autocomplete/CategoryAutocomplete';
-import { ItemHeader } from '../autocomplete/ItemHeader';
-import {
-  PayeeAutocomplete,
-  CreatePayeeButton,
-  PayeeItem,
-} from '../autocomplete/PayeeAutocomplete';
+import { theme } from '../../style';
 import { Button } from '../common/Button';
 import { Input } from '../common/Input';
 import { Modal } from '../common/Modal';
@@ -34,17 +16,13 @@ import { View } from '../common/View';
 import { SectionLabel } from '../forms';
 import { DateSelect } from '../select/DateSelect';
 
-function CreatePayeeIcon(props) {
-  return <SvgAdd {...props} width={14} height={14} />;
-}
+import { AccountAutocompleteModal } from './AccountAutocompleteModal';
+import { CategoryAutocompleteModal } from './CategoryAutocompleteModal';
+import { PayeeAutocompleteModal } from './PayeeAutocompleteModal';
 
 export function EditField({ modalProps, name, onSubmit, onClose }) {
   const dateFormat = useDateFormat() || 'MM/dd/yyyy';
   const { grouped: categoryGroups } = useCategories();
-  const accounts = useAccounts();
-  const payees = usePayees();
-
-  const { createPayee } = useActions();
   const onCloseInner = () => {
     modalProps.onClose();
     onClose?.();
@@ -82,15 +60,11 @@ export function EditField({ modalProps, name, onSubmit, onClose }) {
     ':focus': { boxShadow: 0 },
     ...(isNarrowWidth && itemStyle),
   };
-  const autocompleteProps = {
-    inputProps: { style: inputStyle },
-    containerProps: { style: { height: isNarrowWidth ? '90vh' : 275 } },
-  };
 
   const [noteAmend, onChangeMode] = useState('replace');
 
   switch (name) {
-    case 'date': {
+    case 'date':
       const today = currentDay();
       label = 'Date';
       minWidth = 350;
@@ -107,105 +81,50 @@ export function EditField({ modalProps, name, onSubmit, onClose }) {
         />
       );
       break;
-    }
 
-    case 'account':
-      label = 'Account';
-      editor = (
-        <AccountAutocomplete
-          value={null}
-          accounts={accounts}
-          focused={true}
-          embedded={true}
-          closeOnBlur={false}
-          onSelect={value => {
-            if (value) {
-              onSelect(value);
-            }
+    case 'category':
+      return (
+        <CategoryAutocompleteModal
+          modalProps={modalProps}
+          autocompleteProps={{
+            categoryGroups,
+            showHiddenCategories: false,
+            value: null,
+            onSelect: categoryId => {
+              onSelect(categoryId);
+            },
           }}
-          {...(isNarrowWidth && {
-            renderAccountItemGroupHeader: props => (
-              <ItemHeader
-                {...props}
-                style={{
-                  ...styles.largeText,
-                  color: theme.menuItemTextHeader,
-                  paddingTop: 10,
-                  paddingBottom: 10,
-                }}
-              />
-            ),
-            renderAccountItem: props => (
-              <AccountItem
-                {...props}
-                style={{
-                  ...itemStyle,
-                  color: theme.menuItemText,
-                  borderRadius: 0,
-                  borderTop: `1px solid ${theme.pillBorder}`,
-                }}
-              />
-            ),
-          })}
-          {...autocompleteProps}
+          onClose={onClose}
         />
       );
-      break;
 
     case 'payee':
-      label = 'Payee';
-      editor = (
-        <PayeeAutocomplete
-          payees={payees}
-          accounts={accounts}
-          value={null}
-          focused={true}
-          embedded={true}
-          closeOnBlur={false}
-          showManagePayees={false}
-          showMakeTransfer={!isNarrowWidth}
-          onSelect={async value => {
-            if (value && value.startsWith('new:')) {
-              value = await createPayee(value.slice('new:'.length));
-            }
+      return (
+        <PayeeAutocompleteModal
+          modalProps={modalProps}
+          autocompleteProps={{
+            value: null,
+            onSelect: payeeId => {
+              onSelect(payeeId);
+            },
+          }}
+          onClose={onClose}
+        />
+      );
 
-            onSelect(value);
+    case 'account':
+      return (
+        <AccountAutocompleteModal
+          modalProps={modalProps}
+          autocompleteProps={{
+            value: null,
+            onSelect: accountId => {
+              onSelect(accountId);
+            },
           }}
-          {...(isNarrowWidth && {
-            renderCreatePayeeButton: props => (
-              <CreatePayeeButton
-                {...props}
-                Icon={CreatePayeeIcon}
-                style={itemStyle}
-              />
-            ),
-            renderPayeeItemGroupHeader: props => (
-              <ItemHeader
-                {...props}
-                style={{
-                  ...styles.largeText,
-                  color: theme.menuItemTextHeader,
-                  paddingTop: 10,
-                  paddingBottom: 10,
-                }}
-              />
-            ),
-            renderPayeeItem: props => (
-              <PayeeItem
-                {...props}
-                style={{
-                  ...itemStyle,
-                  color: theme.menuItemText,
-                  borderRadius: 0,
-                  borderTop: `1px solid ${theme.pillBorder}`,
-                }}
-              />
-            ),
-          })}
-          {...autocompleteProps}
+          onClose={onClose}
         />
       );
-      break;
 
     case 'notes':
       label = 'Notes';
@@ -330,50 +249,6 @@ export function EditField({ modalProps, name, onSubmit, onClose }) {
       );
       break;
 
-    case 'category':
-      label = 'Category';
-      editor = (
-        <CategoryAutocomplete
-          categoryGroups={categoryGroups}
-          value={null}
-          focused={true}
-          embedded={true}
-          closeOnBlur={false}
-          showSplitOption={false}
-          onUpdate={() => {}}
-          onSelect={value => {
-            onSelect(value);
-          }}
-          {...(isNarrowWidth && {
-            renderCategoryItemGroupHeader: props => (
-              <ItemHeader
-                {...props}
-                style={{
-                  ...styles.largeText,
-                  color: theme.menuItemTextHeader,
-                  paddingTop: 10,
-                  paddingBottom: 10,
-                }}
-              />
-            ),
-            renderCategoryItem: props => (
-              <CategoryItem
-                {...props}
-                style={{
-                  ...itemStyle,
-                  color: theme.menuItemText,
-                  borderRadius: 0,
-                  borderTop: `1px solid ${theme.pillBorder}`,
-                }}
-              />
-            ),
-          })}
-          {...autocompleteProps}
-          showHiddenItems={false}
-        />
-      );
-      break;
-
     case 'amount':
       label = 'Amount';
       editor = (
diff --git a/packages/desktop-client/src/components/modals/HoldBufferModal.tsx b/packages/desktop-client/src/components/modals/HoldBufferModal.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..74ea959aae54c9bd866dfe33eff82eb589f8a598
--- /dev/null
+++ b/packages/desktop-client/src/components/modals/HoldBufferModal.tsx
@@ -0,0 +1,88 @@
+import React, { useState } from 'react';
+
+import { rolloverBudget } from 'loot-core/client/queries';
+import { evalArithmetic } from 'loot-core/shared/arithmetic';
+import { amountToInteger, integerToCurrency } from 'loot-core/shared/util';
+
+import { styles } from '../../style';
+import { Button } from '../common/Button';
+import { InitialFocus } from '../common/InitialFocus';
+import { Modal } from '../common/Modal';
+import { View } from '../common/View';
+import { FieldLabel, InputField } from '../mobile/MobileForms';
+import { type CommonModalProps } from '../Modals';
+import { useSheetValue } from '../spreadsheet/useSheetValue';
+
+type HoldBufferModalProps = {
+  modalProps: CommonModalProps;
+  month: string;
+  onSubmit: (amount: number) => void;
+};
+
+export function HoldBufferModal({
+  modalProps,
+  onSubmit,
+}: HoldBufferModalProps) {
+  const available = useSheetValue(rolloverBudget.toBudget);
+  const initialAmount = integerToCurrency(Math.max(available, 0));
+  const [amount, setAmount] = useState<string | null>(null);
+
+  const _onSubmit = (newAmount: string | null) => {
+    const parsedAmount = evalArithmetic(newAmount || '');
+    if (parsedAmount) {
+      onSubmit?.(amountToInteger(parsedAmount));
+    }
+
+    modalProps.onClose();
+  };
+
+  return (
+    <Modal
+      title="Hold Buffer"
+      showHeader
+      focusAfterClose={false}
+      {...modalProps}
+      padding={0}
+      style={{
+        flex: 1,
+        padding: '0 10px',
+        paddingBottom: 10,
+        borderRadius: '6px',
+      }}
+    >
+      {() => (
+        <>
+          <View>
+            <FieldLabel title="Hold this amount:" />
+            <InitialFocus>
+              <InputField
+                defaultValue={initialAmount}
+                onUpdate={value => setAmount(value)}
+                onEnter={() => _onSubmit(amount)}
+              />
+            </InitialFocus>
+          </View>
+          <View
+            style={{
+              justifyContent: 'center',
+              alignItems: 'center',
+              marginTop: 10,
+            }}
+          >
+            <Button
+              type="primary"
+              style={{
+                height: styles.mobileMinHeight,
+                marginLeft: styles.mobileEditingPadding,
+                marginRight: styles.mobileEditingPadding,
+              }}
+              onClick={() => _onSubmit(amount)}
+            >
+              Hold
+            </Button>
+          </View>
+        </>
+      )}
+    </Modal>
+  );
+}
diff --git a/packages/desktop-client/src/components/modals/PayeeAutocompleteModal.tsx b/packages/desktop-client/src/components/modals/PayeeAutocompleteModal.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..6eaf1a5a58b849b4d9ea879dee932e51b9a99905
--- /dev/null
+++ b/packages/desktop-client/src/components/modals/PayeeAutocompleteModal.tsx
@@ -0,0 +1,71 @@
+import React, { type ComponentPropsWithoutRef } from 'react';
+
+import { useAccounts } from '../../hooks/useAccounts';
+import { usePayees } from '../../hooks/usePayees';
+import { useResponsive } from '../../ResponsiveProvider';
+import { theme } from '../../style';
+import { PayeeAutocomplete } from '../autocomplete/PayeeAutocomplete';
+import { Modal } from '../common/Modal';
+import { type CommonModalProps } from '../Modals';
+
+type PayeeAutocompleteModalProps = {
+  modalProps: CommonModalProps;
+  autocompleteProps: ComponentPropsWithoutRef<typeof PayeeAutocomplete>;
+  onClose: () => void;
+};
+
+export function PayeeAutocompleteModal({
+  modalProps,
+  autocompleteProps,
+  onClose,
+}: PayeeAutocompleteModalProps) {
+  const payees = usePayees() || [];
+  const accounts = useAccounts() || [];
+
+  const _onClose = () => {
+    modalProps.onClose();
+    onClose?.();
+  };
+
+  const { isNarrowWidth } = useResponsive();
+  const defaultAutocompleteProps = {
+    containerProps: { style: { height: isNarrowWidth ? '90vh' : 275 } },
+  };
+
+  return (
+    <Modal
+      title="Payee"
+      noAnimation={!isNarrowWidth}
+      showHeader={isNarrowWidth}
+      focusAfterClose={false}
+      {...modalProps}
+      onClose={_onClose}
+      padding={0}
+      style={{
+        flex: 0,
+        height: isNarrowWidth ? '85vh' : 275,
+        padding: '15px 10px',
+        borderRadius: '6px',
+        ...(!isNarrowWidth && {
+          backgroundColor: theme.mobileModalBackground,
+          color: theme.mobileModalText,
+        }),
+      }}
+    >
+      {() => (
+        <PayeeAutocomplete
+          payees={payees}
+          accounts={accounts}
+          focused={true}
+          embedded={true}
+          closeOnBlur={false}
+          onClose={_onClose}
+          showManagePayees={false}
+          showMakeTransfer={!isNarrowWidth}
+          {...defaultAutocompleteProps}
+          {...autocompleteProps}
+        />
+      )}
+    </Modal>
+  );
+}
diff --git a/packages/desktop-client/src/components/modals/ReportBalanceMenuModal.tsx b/packages/desktop-client/src/components/modals/ReportBalanceMenuModal.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..6c4d5e6e1eada91c9fba9df240502a0e0632b1b2
--- /dev/null
+++ b/packages/desktop-client/src/components/modals/ReportBalanceMenuModal.tsx
@@ -0,0 +1,49 @@
+import React, { type ComponentPropsWithoutRef } from 'react';
+
+import { type CSSProperties, theme, styles } from '../../style';
+import { BalanceMenu } from '../budget/report/BalanceMenu';
+import { Modal } from '../common/Modal';
+import { type CommonModalProps } from '../Modals';
+
+type ReportBalanceMenuModalProps = ComponentPropsWithoutRef<
+  typeof BalanceMenu
+> & {
+  modalProps: CommonModalProps;
+};
+
+export function ReportBalanceMenuModal({
+  modalProps,
+  categoryId,
+  onCarryover,
+}: ReportBalanceMenuModalProps) {
+  const defaultMenuItemStyle: CSSProperties = {
+    ...styles.mobileMenuItem,
+    color: theme.menuItemText,
+    borderRadius: 0,
+    borderTop: `1px solid ${theme.pillBorder}`,
+  };
+
+  return (
+    <Modal
+      title="Actions"
+      showHeader
+      focusAfterClose={false}
+      {...modalProps}
+      padding={0}
+      style={{
+        flex: 1,
+        padding: '0 10px',
+        paddingBottom: 10,
+        borderRadius: '6px',
+      }}
+    >
+      {() => (
+        <BalanceMenu
+          categoryId={categoryId}
+          getItemStyle={() => defaultMenuItemStyle}
+          onCarryover={onCarryover}
+        />
+      )}
+    </Modal>
+  );
+}
diff --git a/packages/desktop-client/src/components/modals/ReportBudgetSummary.tsx b/packages/desktop-client/src/components/modals/ReportBudgetSummaryModal.tsx
similarity index 92%
rename from packages/desktop-client/src/components/modals/ReportBudgetSummary.tsx
rename to packages/desktop-client/src/components/modals/ReportBudgetSummaryModal.tsx
index d16acc205411bf4f13ecb6c796d2ce77152080c5..a58338ce3b2e8623c213073332c22b2056721fd6 100644
--- a/packages/desktop-client/src/components/modals/ReportBudgetSummary.tsx
+++ b/packages/desktop-client/src/components/modals/ReportBudgetSummaryModal.tsx
@@ -12,15 +12,15 @@ import { Stack } from '../common/Stack';
 import { type CommonModalProps } from '../Modals';
 import { NamespaceContext } from '../spreadsheet/NamespaceContext';
 
-type ReportBudgetSummaryProps = {
+type ReportBudgetSummaryModalProps = {
   modalProps: CommonModalProps;
   month: string;
 };
 
-export function ReportBudgetSummary({
+export function ReportBudgetSummaryModal({
   month,
   modalProps,
-}: ReportBudgetSummaryProps) {
+}: ReportBudgetSummaryModalProps) {
   const currentMonth = monthUtils.currentMonth();
   return (
     <Modal title="Budget Summary" {...modalProps}>
diff --git a/packages/desktop-client/src/components/modals/RolloverBalanceMenuModal.tsx b/packages/desktop-client/src/components/modals/RolloverBalanceMenuModal.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..75c4159103f0ef8903f06c6bbe1b569e10ae6090
--- /dev/null
+++ b/packages/desktop-client/src/components/modals/RolloverBalanceMenuModal.tsx
@@ -0,0 +1,53 @@
+import React, { type ComponentPropsWithoutRef } from 'react';
+
+import { type CSSProperties, theme, styles } from '../../style';
+import { BalanceMenu } from '../budget/rollover/BalanceMenu';
+import { Modal } from '../common/Modal';
+import { type CommonModalProps } from '../Modals';
+
+type RolloverBalanceMenuModalProps = ComponentPropsWithoutRef<
+  typeof BalanceMenu
+> & {
+  modalProps: CommonModalProps;
+};
+
+export function RolloverBalanceMenuModal({
+  modalProps,
+  categoryId,
+  onCarryover,
+  onTransfer,
+  onCover,
+}: RolloverBalanceMenuModalProps) {
+  const defaultMenuItemStyle: CSSProperties = {
+    ...styles.mobileMenuItem,
+    color: theme.menuItemText,
+    borderRadius: 0,
+    borderTop: `1px solid ${theme.pillBorder}`,
+  };
+
+  return (
+    <Modal
+      title="Actions"
+      showHeader
+      focusAfterClose={false}
+      {...modalProps}
+      padding={0}
+      style={{
+        flex: 1,
+        padding: '0 10px',
+        paddingBottom: 10,
+        borderRadius: '6px',
+      }}
+    >
+      {() => (
+        <BalanceMenu
+          categoryId={categoryId}
+          getItemStyle={() => defaultMenuItemStyle}
+          onCarryover={onCarryover}
+          onTransfer={onTransfer}
+          onCover={onCover}
+        />
+      )}
+    </Modal>
+  );
+}
diff --git a/packages/desktop-client/src/components/modals/RolloverBudgetSummary.tsx b/packages/desktop-client/src/components/modals/RolloverBudgetSummary.tsx
deleted file mode 100644
index 58a0e4260cdba149fd11fddd6fdc8c78f2d5ef87..0000000000000000000000000000000000000000
--- a/packages/desktop-client/src/components/modals/RolloverBudgetSummary.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-import React from 'react';
-
-import { format, sheetForMonth, prevMonth } from 'loot-core/src/shared/months';
-
-import { styles } from '../../style';
-import { ToBudget } from '../budget/rollover/budgetsummary/ToBudget';
-import { TotalsList } from '../budget/rollover/budgetsummary/TotalsList';
-import { Modal } from '../common/Modal';
-import { type CommonModalProps } from '../Modals';
-import { NamespaceContext } from '../spreadsheet/NamespaceContext';
-
-type RolloverBudgetSummaryProps = {
-  modalProps: CommonModalProps;
-  onBudgetAction: (idx: string | number, action: string, arg: unknown) => void;
-  month: string;
-};
-
-export function RolloverBudgetSummary({
-  month,
-  onBudgetAction,
-  modalProps,
-}: RolloverBudgetSummaryProps) {
-  const prevMonthName = format(prevMonth(month), 'MMM');
-
-  return (
-    <Modal title="Budget Summary" {...modalProps}>
-      {() => (
-        <NamespaceContext.Provider value={sheetForMonth(month)}>
-          <TotalsList
-            prevMonthName={prevMonthName}
-            style={{
-              ...styles.mediumText,
-            }}
-          />
-          <ToBudget
-            month={month}
-            prevMonthName={prevMonthName}
-            onBudgetAction={onBudgetAction}
-            style={{
-              ...styles.mediumText,
-              marginTop: 15,
-            }}
-            amountStyle={{
-              ...styles.underlinedText,
-            }}
-            totalsTooltipProps={{
-              position: 'bottom-center',
-            }}
-            holdTooltipProps={{
-              position: 'bottom-center',
-            }}
-            transferTooltipProps={{
-              position: 'bottom-center',
-            }}
-          />
-        </NamespaceContext.Provider>
-      )}
-    </Modal>
-  );
-}
diff --git a/packages/desktop-client/src/components/modals/RolloverBudgetSummaryModal.tsx b/packages/desktop-client/src/components/modals/RolloverBudgetSummaryModal.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..2839c3ee666583842099e18797f7884c18033604
--- /dev/null
+++ b/packages/desktop-client/src/components/modals/RolloverBudgetSummaryModal.tsx
@@ -0,0 +1,104 @@
+import React from 'react';
+import { useDispatch } from 'react-redux';
+
+import { collapseModals, pushModal } from 'loot-core/client/actions';
+import { rolloverBudget } from 'loot-core/client/queries';
+import { format, sheetForMonth, prevMonth } from 'loot-core/src/shared/months';
+
+import { styles } from '../../style';
+import { ToBudgetAmount } from '../budget/rollover/budgetsummary/ToBudgetAmount';
+import { TotalsList } from '../budget/rollover/budgetsummary/TotalsList';
+import { Modal } from '../common/Modal';
+import { type CommonModalProps } from '../Modals';
+import { NamespaceContext } from '../spreadsheet/NamespaceContext';
+import { useSheetValue } from '../spreadsheet/useSheetValue';
+
+type RolloverBudgetSummaryModalProps = {
+  modalProps: CommonModalProps;
+  onBudgetAction: (idx: string | number, action: string, arg?: unknown) => void;
+  month: string;
+};
+
+export function RolloverBudgetSummaryModal({
+  month,
+  onBudgetAction,
+  modalProps,
+}: RolloverBudgetSummaryModalProps) {
+  const dispatch = useDispatch();
+  const prevMonthName = format(prevMonth(month), 'MMM');
+  const sheetValue = useSheetValue({
+    name: rolloverBudget.toBudget,
+    value: 0,
+  });
+
+  const openTransferModal = () => {
+    dispatch(
+      pushModal('transfer', {
+        title: 'Transfer',
+        amount: sheetValue,
+        onSubmit: (amount, toCategoryId) => {
+          onBudgetAction?.(month, 'transfer-available', {
+            amount,
+            month,
+            category: toCategoryId,
+          });
+          dispatch(collapseModals('transfer'));
+        },
+      }),
+    );
+  };
+
+  const onHoldBuffer = () => {
+    dispatch(
+      pushModal('hold-buffer', {
+        month,
+        onSubmit: amount => {
+          onBudgetAction(month, 'hold', { amount });
+          dispatch(collapseModals('hold-buffer'));
+        },
+      }),
+    );
+  };
+
+  const onResetHoldBuffer = () => {
+    onBudgetAction?.(month, 'reset-hold');
+    modalProps.onClose();
+  };
+
+  const onClick = () => {
+    dispatch(
+      pushModal('rollover-to-budget-menu', {
+        month,
+        onTransfer: openTransferModal,
+        onResetHoldBuffer,
+        onHoldBuffer,
+      }),
+    );
+  };
+
+  return (
+    <Modal title="Budget Summary" {...modalProps}>
+      {() => (
+        <NamespaceContext.Provider value={sheetForMonth(month)}>
+          <TotalsList
+            prevMonthName={prevMonthName}
+            style={{
+              ...styles.mediumText,
+            }}
+          />
+          <ToBudgetAmount
+            prevMonthName={prevMonthName}
+            style={{
+              ...styles.mediumText,
+              marginTop: 15,
+            }}
+            amountStyle={{
+              ...styles.underlinedText,
+            }}
+            onClick={onClick}
+          />
+        </NamespaceContext.Provider>
+      )}
+    </Modal>
+  );
+}
diff --git a/packages/desktop-client/src/components/modals/RolloverToBudgetMenuModal.tsx b/packages/desktop-client/src/components/modals/RolloverToBudgetMenuModal.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..da62d53d08f696d4e9a5844517d68bcc9f0a3a2c
--- /dev/null
+++ b/packages/desktop-client/src/components/modals/RolloverToBudgetMenuModal.tsx
@@ -0,0 +1,51 @@
+import React, { type ComponentPropsWithoutRef } from 'react';
+
+import { type CSSProperties, theme, styles } from '../../style';
+import { ToBudgetMenu } from '../budget/rollover/budgetsummary/ToBudgetMenu';
+import { Modal } from '../common/Modal';
+import { type CommonModalProps } from '../Modals';
+
+type RolloverToBudgetMenuModalProps = ComponentPropsWithoutRef<
+  typeof ToBudgetMenu
+> & {
+  modalProps: CommonModalProps;
+};
+
+export function RolloverToBudgetMenuModal({
+  modalProps,
+  onTransfer,
+  onHoldBuffer,
+  onResetHoldBuffer,
+}: RolloverToBudgetMenuModalProps) {
+  const defaultMenuItemStyle: CSSProperties = {
+    ...styles.mobileMenuItem,
+    color: theme.menuItemText,
+    borderRadius: 0,
+    borderTop: `1px solid ${theme.pillBorder}`,
+  };
+
+  return (
+    <Modal
+      title="Actions"
+      showHeader
+      focusAfterClose={false}
+      {...modalProps}
+      padding={0}
+      style={{
+        flex: 1,
+        padding: '0 10px',
+        paddingBottom: 10,
+        borderRadius: '6px',
+      }}
+    >
+      {() => (
+        <ToBudgetMenu
+          getItemStyle={() => defaultMenuItemStyle}
+          onTransfer={onTransfer}
+          onHoldBuffer={onHoldBuffer}
+          onResetHoldBuffer={onResetHoldBuffer}
+        />
+      )}
+    </Modal>
+  );
+}
diff --git a/packages/desktop-client/src/components/modals/ScheduledTransactionMenuModal.tsx b/packages/desktop-client/src/components/modals/ScheduledTransactionMenuModal.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..cfadec05dab4e74ebec8f14455330a925129ea52
--- /dev/null
+++ b/packages/desktop-client/src/components/modals/ScheduledTransactionMenuModal.tsx
@@ -0,0 +1,93 @@
+import React, { type ComponentPropsWithoutRef } from 'react';
+
+import { type CSSProperties, theme, styles } from '../../style';
+import { Menu } from '../common/Menu';
+import { Modal } from '../common/Modal';
+import { type CommonModalProps } from '../Modals';
+
+type ScheduledTransactionMenuModalProps = ScheduledTransactionMenuProps & {
+  modalProps: CommonModalProps;
+};
+
+export function ScheduledTransactionMenuModal({
+  modalProps,
+  transactionId,
+  onSkip,
+  onPost,
+}: ScheduledTransactionMenuModalProps) {
+  const defaultMenuItemStyle: CSSProperties = {
+    ...styles.mobileMenuItem,
+    color: theme.menuItemText,
+    borderRadius: 0,
+    borderTop: `1px solid ${theme.pillBorder}`,
+  };
+
+  return (
+    <Modal
+      title="Actions"
+      showHeader
+      focusAfterClose={false}
+      {...modalProps}
+      padding={0}
+      style={{
+        flex: 1,
+        padding: '0 10px',
+        paddingBottom: 10,
+        borderRadius: '6px',
+      }}
+    >
+      {() => (
+        <ScheduledTransactionMenu
+          transactionId={transactionId}
+          onPost={onPost}
+          onSkip={onSkip}
+          getItemStyle={() => defaultMenuItemStyle}
+        />
+      )}
+    </Modal>
+  );
+}
+
+type ScheduledTransactionMenuProps = Omit<
+  ComponentPropsWithoutRef<typeof Menu>,
+  'onMenuSelect' | 'items'
+> & {
+  transactionId: string;
+  onSkip: (transactionId: string) => void;
+  onPost: (transactionId: string) => void;
+};
+
+function ScheduledTransactionMenu({
+  transactionId,
+  onSkip,
+  onPost,
+  ...props
+}: ScheduledTransactionMenuProps) {
+  return (
+    <Menu
+      {...props}
+      onMenuSelect={name => {
+        switch (name) {
+          case 'post':
+            onPost?.(transactionId);
+            break;
+          case 'skip':
+            onSkip?.(transactionId);
+            break;
+          default:
+            throw new Error(`Unrecognized menu option: ${name}`);
+        }
+      }}
+      items={[
+        {
+          name: 'post',
+          text: 'Post transaction',
+        },
+        {
+          name: 'skip',
+          text: 'Skip scheduled date',
+        },
+      ]}
+    />
+  );
+}
diff --git a/packages/desktop-client/src/components/modals/SingleInput.tsx b/packages/desktop-client/src/components/modals/SingleInputModal.tsx
similarity index 51%
rename from packages/desktop-client/src/components/modals/SingleInput.tsx
rename to packages/desktop-client/src/components/modals/SingleInputModal.tsx
index 5906142a400d7a5f792e50fe603e2f62283b2ccb..c95d820fabe9ffceab892d0615babf0c46c6dc37 100644
--- a/packages/desktop-client/src/components/modals/SingleInput.tsx
+++ b/packages/desktop-client/src/components/modals/SingleInputModal.tsx
@@ -5,12 +5,12 @@ import { styles } from '../../style';
 import { Button } from '../common/Button';
 import { FormError } from '../common/FormError';
 import { InitialFocus } from '../common/InitialFocus';
-import { Input } from '../common/Input';
 import { Modal } from '../common/Modal';
 import { View } from '../common/View';
+import { InputField } from '../mobile/MobileForms';
 import { type CommonModalProps } from '../Modals';
 
-type SingleInputProps = {
+type SingleInputModalProps = {
   modalProps: Partial<CommonModalProps>;
   title: string;
   buttonText: string;
@@ -19,14 +19,14 @@ type SingleInputProps = {
   inputPlaceholder?: string;
 };
 
-export function SingleInput({
+export function SingleInputModal({
   modalProps,
   title,
   buttonText,
   onSubmit,
   onValidate,
   inputPlaceholder,
-}: SingleInputProps) {
+}: SingleInputModalProps) {
   const [value, setValue] = useState('');
   const [errorMessage, setErrorMessage] = useState(null);
 
@@ -40,49 +40,57 @@ export function SingleInput({
     onSubmit?.(value);
     modalProps.onClose();
   };
+
   return (
-    <Modal title={title} {...modalProps}>
+    <Modal
+      title={title}
+      {...modalProps}
+      padding={0}
+      style={{
+        flex: 1,
+        padding: '0 10px',
+        paddingBottom: 10,
+        borderRadius: '6px',
+      }}
+    >
       {() => (
         <>
-          <View
-            style={{
-              flexDirection: 'row',
-              justifyContent: 'center',
-              paddingBottom: 15,
-            }}
-          >
-            <View style={{ flexDirection: 'column', flex: 1 }}>
-              <InitialFocus>
-                <Input
-                  placeholder={inputPlaceholder}
-                  style={{ ...styles.mediumText }}
-                  value={value}
-                  onChangeValue={setValue}
-                  onEnter={e => _onSubmit(e.currentTarget.value)}
-                />
-              </InitialFocus>
-              {errorMessage && (
-                <FormError style={{ paddingTop: 5 }}>
-                  * {errorMessage}
-                </FormError>
-              )}
-            </View>
+          <View>
+            <InitialFocus>
+              <InputField
+                placeholder={inputPlaceholder}
+                defaultValue={value}
+                onUpdate={setValue}
+                onEnter={e => _onSubmit(e.currentTarget.value)}
+              />
+            </InitialFocus>
+            {errorMessage && (
+              <FormError
+                style={{
+                  paddingTop: 5,
+                  marginLeft: styles.mobileEditingPadding,
+                  marginRight: styles.mobileEditingPadding,
+                }}
+              >
+                * {errorMessage}
+              </FormError>
+            )}
           </View>
-
           <View
             style={{
-              flexDirection: 'row',
-              alignContent: 'center',
               justifyContent: 'center',
+              alignItems: 'center',
+              marginTop: 10,
             }}
           >
             <Button
               type="primary"
               style={{
-                ...styles.mediumText,
-                flexBasis: '50%',
+                height: styles.mobileMinHeight,
+                marginLeft: styles.mobileEditingPadding,
+                marginRight: styles.mobileEditingPadding,
               }}
-              onPointerUp={() => _onSubmit(value)}
+              onClick={() => _onSubmit(value)}
             >
               {buttonText}
             </Button>
diff --git a/packages/desktop-client/src/components/modals/TransferModal.tsx b/packages/desktop-client/src/components/modals/TransferModal.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..7def9a00471042d4139d252e493100ac94926330
--- /dev/null
+++ b/packages/desktop-client/src/components/modals/TransferModal.tsx
@@ -0,0 +1,129 @@
+import React, { useState } from 'react';
+import { useDispatch } from 'react-redux';
+
+import { pushModal } from 'loot-core/client/actions';
+import { evalArithmetic } from 'loot-core/shared/arithmetic';
+import { amountToInteger, integerToCurrency } from 'loot-core/shared/util';
+
+import { useCategories } from '../../hooks/useCategories';
+import { styles } from '../../style';
+import { addToBeBudgetedGroup } from '../budget/util';
+import { Button } from '../common/Button';
+import { InitialFocus } from '../common/InitialFocus';
+import { Modal } from '../common/Modal';
+import { View } from '../common/View';
+import { FieldLabel, InputField, TapField } from '../mobile/MobileForms';
+import { type CommonModalProps } from '../Modals';
+
+type TransferModalProps = {
+  modalProps: CommonModalProps;
+  title: string;
+  amount: number;
+  showToBeBudgeted: boolean;
+  onSubmit: (amount: number, toCategoryId: string) => void;
+};
+
+export function TransferModal({
+  modalProps,
+  title,
+  amount: initialAmount,
+  showToBeBudgeted,
+  onSubmit,
+}: TransferModalProps) {
+  const { grouped: originalCategoryGroups, list: categories } = useCategories();
+  let categoryGroups = originalCategoryGroups.filter(g => !g.is_income);
+  if (showToBeBudgeted) {
+    categoryGroups = addToBeBudgetedGroup(categoryGroups);
+  }
+
+  const _initialAmount = integerToCurrency(Math.max(initialAmount, 0));
+  const [amount, setAmount] = useState<string | null>(null);
+  const [toCategoryId, setToCategoryId] = useState<string | null>(null);
+  const dispatch = useDispatch();
+
+  const openCategoryModal = () => {
+    dispatch(
+      pushModal('category-autocomplete', {
+        categoryGroups,
+        showHiddenCategories: true,
+        onSelect: categoryId => {
+          setToCategoryId(categoryId);
+        },
+      }),
+    );
+  };
+
+  const _onSubmit = (newAmount: string | null, categoryId: string | null) => {
+    const parsedAmount = evalArithmetic(newAmount || '');
+    if (parsedAmount && categoryId) {
+      onSubmit?.(amountToInteger(parsedAmount), categoryId);
+    }
+
+    modalProps.onClose();
+  };
+
+  return (
+    <Modal
+      title={title}
+      showHeader
+      focusAfterClose={false}
+      {...modalProps}
+      padding={0}
+      style={{
+        flex: 1,
+        padding: '0 10px',
+        paddingBottom: 10,
+        borderRadius: '6px',
+      }}
+    >
+      {() => (
+        <>
+          <View>
+            <FieldLabel title="Transfer this amount:" />
+            <InitialFocus>
+              <InputField
+                tabIndex={1}
+                defaultValue={_initialAmount}
+                onUpdate={setAmount}
+                onEnter={() => {
+                  if (!toCategoryId) {
+                    openCategoryModal();
+                  }
+                }}
+              />
+            </InitialFocus>
+          </View>
+
+          <FieldLabel title="To:" />
+          <TapField
+            tabIndex={2}
+            value={categories.find(c => c.id === toCategoryId)?.name}
+            onClick={openCategoryModal}
+            onFocus={openCategoryModal}
+          />
+
+          <View
+            style={{
+              justifyContent: 'center',
+              alignItems: 'center',
+              marginTop: 10,
+            }}
+          >
+            <Button
+              type="primary"
+              tabIndex={3}
+              style={{
+                height: styles.mobileMinHeight,
+                marginLeft: styles.mobileEditingPadding,
+                marginRight: styles.mobileEditingPadding,
+              }}
+              onClick={() => _onSubmit(amount, toCategoryId)}
+            >
+              Transfer
+            </Button>
+          </View>
+        </>
+      )}
+    </Modal>
+  );
+}
diff --git a/packages/desktop-client/src/hooks/useInitialMount.ts b/packages/desktop-client/src/hooks/useInitialMount.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6d6b2d990e925f44d787dfa6a6d5132992cb1909
--- /dev/null
+++ b/packages/desktop-client/src/hooks/useInitialMount.ts
@@ -0,0 +1,12 @@
+import { useRef } from 'react';
+
+export function useInitialMount(): boolean {
+  const initial = useRef(true);
+
+  if (initial.current) {
+    initial.current = false;
+    return true;
+  }
+
+  return false;
+}
diff --git a/packages/loot-core/src/client/state-types/modals.d.ts b/packages/loot-core/src/client/state-types/modals.d.ts
index c4d54d17d93a389b4f0e2055cd3c3d95c76f6181..f780f445e7f4c66c7072bb20b4beabdc15c4e868 100644
--- a/packages/loot-core/src/client/state-types/modals.d.ts
+++ b/packages/loot-core/src/client/state-types/modals.d.ts
@@ -103,6 +103,24 @@ type FinanceModals = {
     onClose: () => void;
   };
 
+  'category-autocomplete': {
+    categoryGroups: CategoryGroupEntity[];
+    onSelect: (categoryId: string, categoryName: string) => void;
+    showHiddenCategories?: boolean;
+    onClose?: () => void;
+  };
+
+  'account-autocomplete': {
+    onSelect: (accountId: string, accountName: string) => void;
+    includeClosedAccounts?: boolean;
+    onClose?: () => void;
+  };
+
+  'payee-autocomplete': {
+    onSelect: (payeeId: string) => void;
+    onClose?: () => void;
+  };
+
   'budget-summary': {
     month: string;
   };
@@ -115,6 +133,14 @@ type FinanceModals = {
 
   'schedule-posts-offline-notification': null;
   'switch-budget-type': { onSwitch: () => void };
+  'account-menu': {
+    accountId: string;
+    onSave: (account: AccountEntity) => void;
+    onCloseAccount: (accountId: string) => void;
+    onReopenAccount: (accountId: string) => void;
+    onEditNotes: (id: string) => void;
+    onClose?: () => void;
+  };
   'category-menu': {
     categoryId: string;
     onSave: (category: CategoryEntity) => void;
@@ -152,6 +178,43 @@ type FinanceModals = {
     onValidate?: (value: string) => string;
     onSubmit: (value: string) => Promise<void>;
   };
+  'rollover-balance-menu': {
+    categoryId: string;
+    month: string;
+    onCarryover: (carryover: boolean) => void;
+    onTransfer: () => void;
+    onCover: () => void;
+  };
+  'rollover-to-budget-menu': {
+    month: string;
+    onTransfer: () => void;
+    onHoldBuffer: () => void;
+    onResetHoldBuffer: () => void;
+  };
+  'report-balance-menu': {
+    categoryId: string;
+    month: string;
+    onCarryover: (carryover: boolean) => void;
+  };
+  transfer: {
+    title: string;
+    amount: number;
+    onSubmit: (amount: number, toCategoryId: string) => void;
+    showToBeBudgeted?: boolean;
+  };
+  cover: {
+    categoryId: string;
+    onSubmit: (fromCategoryId: string) => void;
+  };
+  'hold-buffer': {
+    month: string;
+    onSubmit: (amount: number) => void;
+  };
+  'scheduled-transaction-menu': {
+    transactionId: string;
+    onPost: (transactionId: string) => void;
+    onSkip: (transactionId: string) => void;
+  };
 };
 
 export type PushModalAction = {
diff --git a/upcoming-release-notes/2472.md b/upcoming-release-notes/2472.md
new file mode 100644
index 0000000000000000000000000000000000000000..dcbd90e59d6c66a97fc53f9ea4034bf2eb8b47f4
--- /dev/null
+++ b/upcoming-release-notes/2472.md
@@ -0,0 +1,6 @@
+---
+category: Enhancements
+authors: [joel-jeremy]
+---
+
+Add more modals in mobile for account, scheduled transactions, budget summary, and balance actions.