diff --git a/packages/desktop-client/src/components/accounts/Account.js b/packages/desktop-client/src/components/accounts/Account.js
index ab0105a217edf99ecd813dc8d133db8bbadc3151..d67b3cb3c8d364bfd54b0baa43020e982cccd7b1 100644
--- a/packages/desktop-client/src/components/accounts/Account.js
+++ b/packages/desktop-client/src/components/accounts/Account.js
@@ -1,11 +1,4 @@
-import React, {
-  PureComponent,
-  createRef,
-  memo,
-  useState,
-  useRef,
-  useMemo,
-} from 'react';
+import React, { PureComponent, createRef, useMemo } from 'react';
 import { useSelector, useDispatch } from 'react-redux';
 import { Navigate, useParams, useLocation, useMatch } from 'react-router-dom';
 
@@ -29,59 +22,20 @@ import {
   ungroupTransaction,
   ungroupTransactions,
 } from 'loot-core/src/shared/transactions';
-import {
-  currencyToInteger,
-  applyChanges,
-  groupById,
-} from 'loot-core/src/shared/util';
+import { applyChanges, groupById } from 'loot-core/src/shared/util';
 
-import {
-  SelectedProviderWithItems,
-  useSelectedItems,
-} from '../../hooks/useSelected';
-import useSyncServerStatus from '../../hooks/useSyncServerStatus';
-import Loading from '../../icons/AnimatedLoading';
-import Add from '../../icons/v1/Add';
-import DotsHorizontalTriple from '../../icons/v1/DotsHorizontalTriple';
-import ArrowButtonRight1 from '../../icons/v2/ArrowButtonRight1';
-import ArrowsExpand3 from '../../icons/v2/ArrowsExpand3';
-import ArrowsShrink3 from '../../icons/v2/ArrowsShrink3';
-import CheckCircle1 from '../../icons/v2/CheckCircle1';
-import DownloadThickBottom from '../../icons/v2/DownloadThickBottom';
-import Pencil1 from '../../icons/v2/Pencil1';
-import SvgRemove from '../../icons/v2/Remove';
-import SearchAlternate from '../../icons/v2/SearchAlternate';
+import { SelectedProviderWithItems } from '../../hooks/useSelected';
 import { authorizeBank } from '../../nordigen';
 import { styles, colors } from '../../style';
-import { usePushModal } from '../../util/router-tools';
 import { useActiveLocation } from '../ActiveLocation';
-import AnimatedRefresh from '../AnimatedRefresh';
-import {
-  View,
-  Text,
-  Button,
-  Input,
-  InputWithContent,
-  InitialFocus,
-  Tooltip,
-  Menu,
-  Stack,
-} from '../common';
-import { FilterButton } from '../filters/FiltersMenu';
-import { FiltersStack } from '../filters/SavedFilters';
-import { KeyHandlers } from '../KeyHandlers';
-import NotesButton from '../NotesButton';
-import CellValue from '../spreadsheet/CellValue';
-import format from '../spreadsheet/format';
-import useSheetValue from '../spreadsheet/useSheetValue';
-import { SelectedItemsButton } from '../table';
-
-import TransactionList from './TransactionList';
+import { View, Text, Button } from '../common';
+import TransactionList from '../transactions/TransactionList';
 import {
   SplitsExpandedProvider,
   useSplitsExpanded,
-  isPreviewId,
-} from './TransactionsTable';
+} from '../transactions/TransactionsTable';
+
+import { AccountHeader } from './Header';
 
 function EmptyMessage({ onAdd }) {
   return (
@@ -120,886 +74,6 @@ function EmptyMessage({ onAdd }) {
   );
 }
 
-function ReconcilingMessage({
-  balanceQuery,
-  targetBalance,
-  onDone,
-  onCreateTransaction,
-}) {
-  let cleared = useSheetValue({
-    name: balanceQuery.name + '-cleared',
-    value: 0,
-    query: balanceQuery.query.filter({ cleared: true }),
-  });
-  let targetDiff = targetBalance - cleared;
-
-  return (
-    <View
-      style={{
-        flexDirection: 'row',
-        alignSelf: 'center',
-        backgroundColor: 'white',
-        ...styles.shadow,
-        borderRadius: 4,
-        marginTop: 5,
-        marginBottom: 15,
-        padding: 10,
-      }}
-    >
-      <View style={{ flexDirection: 'row', alignItems: 'center' }}>
-        {targetDiff === 0 ? (
-          <View
-            style={{
-              color: colors.g4,
-              flex: 1,
-              flexDirection: 'row',
-              alignItems: 'center',
-              justifyContent: 'center',
-            }}
-          >
-            <CheckCircle1
-              style={{
-                width: 13,
-                height: 13,
-                color: colors.g5,
-                marginRight: 3,
-              }}
-            />
-            All reconciled!
-          </View>
-        ) : (
-          <View style={{ color: colors.n3 }}>
-            <Text style={{ fontStyle: 'italic', textAlign: 'center' }}>
-              Your cleared balance{' '}
-              <strong>{format(cleared, 'financial')}</strong> needs{' '}
-              <strong>
-                {(targetDiff > 0 ? '+' : '') + format(targetDiff, 'financial')}
-              </strong>{' '}
-              to match
-              <br /> your bank’s balance of{' '}
-              <Text style={{ fontWeight: 700 }}>
-                {format(targetBalance, 'financial')}
-              </Text>
-            </Text>
-          </View>
-        )}
-        <View style={{ marginLeft: 15 }}>
-          <Button primary onClick={onDone}>
-            Done Reconciling
-          </Button>
-        </View>
-        {targetDiff !== 0 && (
-          <View style={{ marginLeft: 15 }}>
-            <Button onClick={() => onCreateTransaction(targetDiff)}>
-              Create Reconciliation Transaction
-            </Button>
-          </View>
-        )}
-      </View>
-    </View>
-  );
-}
-
-function ReconcileTooltip({ account, onReconcile, onClose }) {
-  let balance = useSheetValue(queries.accountBalance(account));
-
-  function onSubmit(e) {
-    e.preventDefault();
-    let input = e.target.elements[0];
-    let amount = currencyToInteger(input.value);
-    if (amount != null) {
-      onReconcile(amount == null ? balance : amount);
-      onClose();
-    } else {
-      input.select();
-    }
-  }
-
-  return (
-    <Tooltip position="bottom-right" width={275} onClose={onClose}>
-      <View style={{ padding: '5px 8px' }}>
-        <Text>
-          Enter the current balance of your bank account that you want to
-          reconcile with:
-        </Text>
-        <form onSubmit={onSubmit}>
-          {balance != null && (
-            <InitialFocus>
-              <Input
-                defaultValue={format(balance, 'financial')}
-                style={{ margin: '7px 0' }}
-              />
-            </InitialFocus>
-          )}
-          <Button primary>Reconcile</Button>
-        </form>
-      </View>
-    </Tooltip>
-  );
-}
-
-function MenuButton({ onClick }) {
-  return (
-    <Button bare onClick={onClick} aria-label="Menu">
-      <DotsHorizontalTriple
-        width={15}
-        height={15}
-        style={{ color: 'inherit', transform: 'rotateZ(90deg)' }}
-      />
-    </Button>
-  );
-}
-
-export function MenuTooltip({ width, onClose, children }) {
-  return (
-    <Tooltip
-      position="bottom-right"
-      width={width}
-      style={{ padding: 0 }}
-      onClose={onClose}
-    >
-      {children}
-    </Tooltip>
-  );
-}
-
-function AccountMenu({
-  account,
-  canSync,
-  showBalances,
-  canShowBalances,
-  showCleared,
-  onClose,
-  onReconcile,
-  onMenuSelect,
-}) {
-  let [tooltip, setTooltip] = useState('default');
-  const syncServerStatus = useSyncServerStatus();
-
-  return tooltip === 'reconcile' ? (
-    <ReconcileTooltip
-      account={account}
-      onClose={onClose}
-      onReconcile={onReconcile}
-    />
-  ) : (
-    <MenuTooltip width={200} onClose={onClose}>
-      <Menu
-        onMenuSelect={item => {
-          if (item === 'reconcile') {
-            setTooltip('reconcile');
-          } else {
-            onMenuSelect(item);
-          }
-        }}
-        items={[
-          canShowBalances && {
-            name: 'toggle-balance',
-            text: (showBalances ? 'Hide' : 'Show') + ' Running Balance',
-          },
-          {
-            name: 'toggle-cleared',
-            text: (showCleared ? 'Hide' : 'Show') + ' “Cleared” Checkboxes',
-          },
-          { name: 'export', text: 'Export' },
-          { name: 'reconcile', text: 'Reconcile' },
-          account &&
-            !account.closed &&
-            (canSync
-              ? {
-                  name: 'unlink',
-                  text: 'Unlink Account',
-                }
-              : syncServerStatus === 'online' && {
-                  name: 'link',
-                  text: 'Link Account',
-                }),
-          account.closed
-            ? { name: 'reopen', text: 'Reopen Account' }
-            : { name: 'close', text: 'Close Account' },
-        ].filter(x => x)}
-      />
-    </MenuTooltip>
-  );
-}
-
-function CategoryMenu({ onClose, onMenuSelect }) {
-  return (
-    <MenuTooltip width={200} onClose={onClose}>
-      <Menu
-        onMenuSelect={item => {
-          onMenuSelect(item);
-        }}
-        items={[{ name: 'export', text: 'Export' }]}
-      />
-    </MenuTooltip>
-  );
-}
-
-function DetailedBalance({ name, balance }) {
-  return (
-    <Text
-      style={{
-        marginLeft: 15,
-        backgroundColor: colors.n9,
-        borderRadius: 4,
-        padding: '4px 6px',
-        color: colors.n5,
-      }}
-    >
-      {name}{' '}
-      <Text style={{ fontWeight: 600 }}>{format(balance, 'financial')}</Text>
-    </Text>
-  );
-}
-
-function SelectedBalance({ selectedItems, account }) {
-  let name = `selected-balance-${[...selectedItems].join('-')}`;
-
-  let rows = useSheetValue({
-    name,
-    query: q('transactions')
-      .filter({
-        id: { $oneof: [...selectedItems] },
-        parent_id: { $oneof: [...selectedItems] },
-      })
-      .select('id'),
-  });
-  let ids = new Set((rows || []).map(r => r.id));
-
-  let finalIds = [...selectedItems].filter(id => !ids.has(id));
-  let balance = useSheetValue({
-    name: name + '-sum',
-    query: q('transactions')
-      .filter({ id: { $oneof: finalIds } })
-      .options({ splits: 'all' })
-      .calculate({ $sum: '$amount' }),
-  });
-
-  let scheduleBalance = null;
-  let scheduleData = useCachedSchedules();
-  let schedules = scheduleData ? scheduleData.schedules : [];
-  let previewIds = [...selectedItems]
-    .filter(id => isPreviewId(id))
-    .map(id => id.slice(8));
-  for (let s of schedules) {
-    if (previewIds.includes(s.id)) {
-      if (!account || account.id === s._account) {
-        scheduleBalance += s._amount;
-      } else {
-        scheduleBalance -= s._amount;
-      }
-    }
-  }
-
-  if (balance == null) {
-    if (scheduleBalance == null) {
-      return null;
-    } else {
-      balance = scheduleBalance;
-    }
-  } else if (scheduleBalance != null) {
-    balance += scheduleBalance;
-  }
-
-  return <DetailedBalance name="Selected balance:" balance={balance} />;
-}
-
-function MoreBalances({ balanceQuery }) {
-  let cleared = useSheetValue({
-    name: balanceQuery.name + '-cleared',
-    query: balanceQuery.query.filter({ cleared: true }),
-  });
-  let uncleared = useSheetValue({
-    name: balanceQuery.name + '-uncleared',
-    query: balanceQuery.query.filter({ cleared: false }),
-  });
-
-  return (
-    <View style={{ flexDirection: 'row' }}>
-      <DetailedBalance name="Cleared total:" balance={cleared} />
-      <DetailedBalance name="Uncleared total:" balance={uncleared} />
-    </View>
-  );
-}
-
-function Balances({
-  balanceQuery,
-  showExtraBalances,
-  onToggleExtraBalances,
-  account,
-}) {
-  let selectedItems = useSelectedItems();
-
-  return (
-    <View
-      style={{
-        flexDirection: 'row',
-        alignItems: 'center',
-        marginTop: -5,
-        marginLeft: -5,
-      }}
-    >
-      <Button
-        data-testid="account-balance"
-        bare
-        onClick={onToggleExtraBalances}
-        style={{
-          '& svg': {
-            opacity: selectedItems.size > 0 || showExtraBalances ? 1 : 0,
-          },
-          '&:hover svg': { opacity: 1 },
-        }}
-      >
-        <CellValue
-          binding={{ ...balanceQuery, value: 0 }}
-          type="financial"
-          style={{ fontSize: 22, fontWeight: 400 }}
-          getStyle={value => ({
-            color: value < 0 ? colors.r5 : value > 0 ? colors.g5 : colors.n8,
-          })}
-        />
-
-        <ArrowButtonRight1
-          style={{
-            width: 10,
-            height: 10,
-            marginLeft: 10,
-            color: colors.n5,
-            transform: showExtraBalances ? 'rotateZ(180deg)' : 'rotateZ(0)',
-          }}
-        />
-      </Button>
-      {showExtraBalances && <MoreBalances balanceQuery={balanceQuery} />}
-
-      {selectedItems.size > 0 && (
-        <SelectedBalance selectedItems={selectedItems} account={account} />
-      )}
-    </View>
-  );
-}
-
-function SelectedTransactionsButton({
-  getTransaction,
-  onShow,
-  onDuplicate,
-  onDelete,
-  onEdit,
-  onUnlink,
-  onCreateRule,
-  onScheduleAction,
-}) {
-  let pushModal = usePushModal();
-  let selectedItems = useSelectedItems();
-
-  let types = useMemo(() => {
-    let items = [...selectedItems];
-    return {
-      preview: !!items.find(id => isPreviewId(id)),
-      trans: !!items.find(id => !isPreviewId(id)),
-    };
-  }, [selectedItems]);
-
-  let ambiguousDuplication = useMemo(() => {
-    let transactions = [...selectedItems].map(id => getTransaction(id));
-
-    return transactions.some(t => t && t.is_child);
-  }, [selectedItems]);
-
-  let linked = useMemo(() => {
-    return (
-      !types.preview &&
-      [...selectedItems].every(id => {
-        let t = getTransaction(id);
-        return t && t.schedule;
-      })
-    );
-  }, [types.preview, selectedItems, getTransaction]);
-
-  return (
-    <SelectedItemsButton
-      name="transactions"
-      keyHandlers={
-        types.trans && {
-          f: () => onShow([...selectedItems]),
-          d: () => onDelete([...selectedItems]),
-          a: () => onEdit('account', [...selectedItems]),
-          p: () => onEdit('payee', [...selectedItems]),
-          n: () => onEdit('notes', [...selectedItems]),
-          c: () => onEdit('category', [...selectedItems]),
-          l: () => onEdit('cleared', [...selectedItems]),
-        }
-      }
-      items={[
-        ...(!types.trans
-          ? [
-              { name: 'view-schedule', text: 'View schedule' },
-              { name: 'post-transaction', text: 'Post transaction' },
-              { name: 'skip', text: 'Skip scheduled date' },
-            ]
-          : [
-              { name: 'show', text: 'Show', key: 'F' },
-              {
-                name: 'duplicate',
-                text: 'Duplicate',
-                disabled: ambiguousDuplication,
-              },
-              { name: 'delete', text: 'Delete', key: 'D' },
-              ...(linked
-                ? [
-                    {
-                      name: 'view-schedule',
-                      text: 'View schedule',
-                      disabled: selectedItems.size > 1,
-                    },
-                    { name: 'unlink-schedule', text: 'Unlink schedule' },
-                  ]
-                : [
-                    {
-                      name: 'link-schedule',
-                      text: 'Link schedule',
-                    },
-                    {
-                      name: 'create-rule',
-                      text: 'Create rule',
-                    },
-                  ]),
-              Menu.line,
-              { type: Menu.label, name: 'Edit field' },
-              { name: 'date', text: 'Date' },
-              { name: 'account', text: 'Account', key: 'A' },
-              { name: 'payee', text: 'Payee', key: 'P' },
-              { name: 'notes', text: 'Notes', key: 'N' },
-              { name: 'category', text: 'Category', key: 'C' },
-              { name: 'amount', text: 'Amount' },
-              { name: 'cleared', text: 'Cleared', key: 'L' },
-            ]),
-      ]}
-      onSelect={name => {
-        switch (name) {
-          case 'show':
-            onShow([...selectedItems]);
-            break;
-          case 'duplicate':
-            onDuplicate([...selectedItems]);
-            break;
-          case 'delete':
-            onDelete([...selectedItems]);
-            break;
-          case 'post-transaction':
-          case 'skip':
-            onScheduleAction(name, selectedItems);
-            break;
-          case 'view-schedule':
-            let firstId = [...selectedItems][0];
-            let scheduleId;
-            if (isPreviewId(firstId)) {
-              let parts = firstId.split('/');
-              scheduleId = parts[1];
-            } else {
-              let trans = getTransaction(firstId);
-              scheduleId = trans && trans.schedule;
-            }
-
-            if (scheduleId) {
-              pushModal(`/schedule/edit/${scheduleId}`);
-            }
-            break;
-          case 'link-schedule':
-            pushModal('/schedule/link', {
-              transactionIds: [...selectedItems],
-            });
-            break;
-          case 'unlink-schedule':
-            onUnlink([...selectedItems]);
-            break;
-          case 'create-rule':
-            onCreateRule([...selectedItems]);
-            break;
-          default:
-            onEdit(name, [...selectedItems]);
-        }
-      }}
-    ></SelectedItemsButton>
-  );
-}
-
-const AccountHeader = memo(
-  ({
-    tableRef,
-    editingName,
-    isNameEditable,
-    workingHard,
-    accountName,
-    account,
-    filterId,
-    filtersList,
-    accountsSyncing,
-    accounts,
-    transactions,
-    showBalances,
-    showExtraBalances,
-    showCleared,
-    showEmptyMessage,
-    balanceQuery,
-    reconcileAmount,
-    canCalculateBalance,
-    search,
-    filters,
-    conditionsOp,
-    savePrefs,
-    onSearch,
-    onAddTransaction,
-    onShowTransactions,
-    onDoneReconciling,
-    onCreateReconciliationTransaction,
-    onToggleExtraBalances,
-    onSaveName,
-    onExposeName,
-    onSync,
-    onImport,
-    onMenuSelect,
-    onReconcile,
-    onBatchDelete,
-    onBatchDuplicate,
-    onBatchEdit,
-    onBatchUnlink,
-    onCreateRule,
-    onApplyFilter,
-    onUpdateFilter,
-    onClearFilters,
-    onReloadSavedFilter,
-    onCondOpChange,
-    onDeleteFilter,
-    onScheduleAction,
-  }) => {
-    let [menuOpen, setMenuOpen] = useState(false);
-    let searchInput = useRef(null);
-    let splitsExpanded = useSplitsExpanded();
-
-    let canSync = account && account.account_id;
-    if (!account) {
-      // All accounts - check for any syncable account
-      canSync = !!accounts.find(account => !!account.account_id);
-    }
-
-    function onToggleSplits() {
-      if (tableRef.current) {
-        splitsExpanded.dispatch({
-          type: 'switch-mode',
-          id: tableRef.current.getScrolledItem(),
-        });
-
-        savePrefs({
-          'expand-splits': !(splitsExpanded.state.mode === 'expand'),
-        });
-      }
-    }
-
-    return (
-      <>
-        <KeyHandlers
-          keys={{
-            'ctrl+f, cmd+f': () => {
-              if (searchInput.current) {
-                searchInput.current.focus();
-              }
-            },
-          }}
-        />
-
-        <View
-          style={[styles.pageContent, { paddingBottom: 10, flexShrink: 0 }]}
-        >
-          <View style={{ marginTop: 2, alignItems: 'flex-start' }}>
-            <View>
-              {editingName ? (
-                <InitialFocus>
-                  <Input
-                    defaultValue={accountName}
-                    onEnter={e => onSaveName(e.target.value)}
-                    onBlur={() => onExposeName(false)}
-                    style={{
-                      fontSize: 25,
-                      fontWeight: 500,
-                      marginTop: -5,
-                      marginBottom: -2,
-                      marginLeft: -5,
-                    }}
-                  />
-                </InitialFocus>
-              ) : isNameEditable ? (
-                <View
-                  style={{
-                    flexDirection: 'row',
-                    alignItems: 'center',
-                    gap: 3,
-                    '& .hover-visible': {
-                      opacity: 0,
-                      transition: 'opacity .25s',
-                    },
-                    '&:hover .hover-visible': {
-                      opacity: 1,
-                    },
-                  }}
-                >
-                  <View
-                    style={{
-                      fontSize: 25,
-                      fontWeight: 500,
-                      marginRight: 5,
-                      marginBottom: 5,
-                    }}
-                    data-testid="account-name"
-                  >
-                    {account && account.closed
-                      ? 'Closed: ' + accountName
-                      : accountName}
-                  </View>
-
-                  {account && <NotesButton id={`account-${account.id}`} />}
-                  <Button
-                    bare
-                    className="hover-visible"
-                    onClick={() => onExposeName(true)}
-                  >
-                    <Pencil1
-                      style={{
-                        width: 11,
-                        height: 11,
-                        color: colors.n8,
-                      }}
-                    />
-                  </Button>
-                </View>
-              ) : (
-                <View
-                  style={{ fontSize: 25, fontWeight: 500, marginBottom: 5 }}
-                  data-testid="account-name"
-                >
-                  {account && account.closed
-                    ? 'Closed: ' + accountName
-                    : accountName}
-                </View>
-              )}
-            </View>
-          </View>
-
-          <Balances
-            balanceQuery={balanceQuery}
-            showExtraBalances={showExtraBalances}
-            onToggleExtraBalances={onToggleExtraBalances}
-            account={account}
-          />
-
-          <Stack
-            spacing={2}
-            direction="row"
-            align="center"
-            style={{ marginTop: 12 }}
-          >
-            {((account && !account.closed) || canSync) && (
-              <Button bare onClick={canSync ? onSync : onImport}>
-                {canSync ? (
-                  <>
-                    <AnimatedRefresh
-                      width={13}
-                      height={13}
-                      animating={
-                        (account && accountsSyncing === account.name) ||
-                        accountsSyncing === '__all'
-                      }
-                      style={{ color: 'currentColor', marginRight: 4 }}
-                    />{' '}
-                    Sync
-                  </>
-                ) : (
-                  <>
-                    <DownloadThickBottom
-                      width={13}
-                      height={13}
-                      style={{ color: 'currentColor', marginRight: 4 }}
-                    />{' '}
-                    Import
-                  </>
-                )}
-              </Button>
-            )}
-            {!showEmptyMessage && (
-              <Button bare onClick={onAddTransaction}>
-                <Add
-                  width={10}
-                  height={10}
-                  style={{ color: 'inherit', marginRight: 3 }}
-                />{' '}
-                Add New
-              </Button>
-            )}
-            <View>
-              <FilterButton onApply={onApplyFilter} />
-            </View>
-            <InputWithContent
-              leftContent={
-                <SearchAlternate
-                  style={{
-                    width: 13,
-                    height: 13,
-                    flexShrink: 0,
-                    color: search ? colors.p7 : 'inherit',
-                    margin: 5,
-                    marginRight: 0,
-                  }}
-                />
-              }
-              rightContent={
-                search && (
-                  <Button
-                    bare
-                    style={{ padding: 8 }}
-                    onClick={() => onSearch('')}
-                    title="Clear search term"
-                  >
-                    <SvgRemove
-                      style={{
-                        width: 8,
-                        height: 8,
-                        color: 'inherit',
-                      }}
-                    />
-                  </Button>
-                )
-              }
-              inputRef={searchInput}
-              value={search}
-              placeholder="Search"
-              onKeyDown={e => {
-                if (e.key === 'Escape') onSearch('');
-              }}
-              getStyle={focused => [
-                {
-                  backgroundColor: 'transparent',
-                  borderWidth: 0,
-                  boxShadow: 'none',
-                  transition: 'color .15s',
-                  '& input::placeholder': {
-                    color: colors.n1,
-                    transition: 'color .25s',
-                  },
-                },
-                focused && { boxShadow: '0 0 0 2px ' + colors.b5 },
-                !focused && search !== '' && { color: colors.p4 },
-              ]}
-              onChange={e => onSearch(e.target.value)}
-            />
-            {workingHard ? (
-              <View>
-                <Loading color={colors.n1} style={{ width: 16, height: 16 }} />
-              </View>
-            ) : (
-              <SelectedTransactionsButton
-                getTransaction={id => transactions.find(t => t.id === id)}
-                onShow={onShowTransactions}
-                onDuplicate={onBatchDuplicate}
-                onDelete={onBatchDelete}
-                onEdit={onBatchEdit}
-                onUnlink={onBatchUnlink}
-                onCreateRule={onCreateRule}
-                onScheduleAction={onScheduleAction}
-              />
-            )}
-            <Button
-              bare
-              disabled={search !== '' || filters.length > 0}
-              style={{ padding: 6 }}
-              onClick={onToggleSplits}
-              title={
-                splitsExpanded.state.mode === 'collapse'
-                  ? 'Collapse split transactions'
-                  : 'Expand split transactions'
-              }
-            >
-              {splitsExpanded.state.mode === 'collapse' ? (
-                <ArrowsShrink3
-                  style={{
-                    width: 14,
-                    height: 14,
-                    color: 'inherit',
-                  }}
-                />
-              ) : (
-                <ArrowsExpand3
-                  style={{
-                    width: 14,
-                    height: 14,
-                    color: 'inherit',
-                  }}
-                />
-              )}
-            </Button>
-            {account ? (
-              <View>
-                <MenuButton onClick={() => setMenuOpen(true)} />
-
-                {menuOpen && (
-                  <AccountMenu
-                    account={account}
-                    canSync={canSync}
-                    canShowBalances={canCalculateBalance()}
-                    showBalances={showBalances}
-                    showCleared={showCleared}
-                    onMenuSelect={item => {
-                      setMenuOpen(false);
-                      onMenuSelect(item);
-                    }}
-                    onReconcile={onReconcile}
-                    onClose={() => setMenuOpen(false)}
-                  />
-                )}
-              </View>
-            ) : (
-              <View>
-                <MenuButton onClick={() => setMenuOpen(true)} />
-
-                {menuOpen && (
-                  <CategoryMenu
-                    onMenuSelect={item => {
-                      setMenuOpen(false);
-                      onMenuSelect(item);
-                    }}
-                    onClose={() => setMenuOpen(false)}
-                  />
-                )}
-              </View>
-            )}
-          </Stack>
-
-          {filters && filters.length > 0 && (
-            <FiltersStack
-              filters={filters}
-              conditionsOp={conditionsOp}
-              onUpdateFilter={onUpdateFilter}
-              onDeleteFilter={onDeleteFilter}
-              onClearFilters={onClearFilters}
-              onReloadSavedFilter={onReloadSavedFilter}
-              filterId={filterId}
-              filtersList={filtersList}
-              onCondOpChange={onCondOpChange}
-            />
-          )}
-        </View>
-        {reconcileAmount != null && (
-          <ReconcilingMessage
-            targetBalance={reconcileAmount}
-            balanceQuery={balanceQuery}
-            onDone={onDoneReconciling}
-            onCreateTransaction={onCreateReconciliationTransaction}
-          />
-        )}
-      </>
-    );
-  },
-);
-
 function AllTransactions({ account = {}, transactions, filtered, children }) {
   const { id: accountId } = account;
   let scheduleData = useCachedSchedules();
diff --git a/packages/desktop-client/src/components/accounts/Balance.js b/packages/desktop-client/src/components/accounts/Balance.js
new file mode 100644
index 0000000000000000000000000000000000000000..186321ba5548760412018567e4c3bce491df81a8
--- /dev/null
+++ b/packages/desktop-client/src/components/accounts/Balance.js
@@ -0,0 +1,156 @@
+import React from 'react';
+
+import { useCachedSchedules } from 'loot-core/src/client/data-hooks/schedules';
+import q from 'loot-core/src/client/query-helpers';
+
+import { useSelectedItems } from '../../hooks/useSelected';
+import ArrowButtonRight1 from '../../icons/v2/ArrowButtonRight1';
+import { colors } from '../../style';
+import { View, Text, Button } from '../common';
+import CellValue from '../spreadsheet/CellValue';
+import format from '../spreadsheet/format';
+import useSheetValue from '../spreadsheet/useSheetValue';
+import { isPreviewId } from '../transactions/TransactionsTable';
+
+function DetailedBalance({ name, balance }) {
+  return (
+    <Text
+      style={{
+        marginLeft: 15,
+        backgroundColor: colors.n9,
+        borderRadius: 4,
+        padding: '4px 6px',
+        color: colors.n5,
+      }}
+    >
+      {name}{' '}
+      <Text style={{ fontWeight: 600 }}>{format(balance, 'financial')}</Text>
+    </Text>
+  );
+}
+
+function SelectedBalance({ selectedItems, account }) {
+  let name = `selected-balance-${[...selectedItems].join('-')}`;
+
+  let rows = useSheetValue({
+    name,
+    query: q('transactions')
+      .filter({
+        id: { $oneof: [...selectedItems] },
+        parent_id: { $oneof: [...selectedItems] },
+      })
+      .select('id'),
+  });
+  let ids = new Set((rows || []).map(r => r.id));
+
+  let finalIds = [...selectedItems].filter(id => !ids.has(id));
+  let balance = useSheetValue({
+    name: name + '-sum',
+    query: q('transactions')
+      .filter({ id: { $oneof: finalIds } })
+      .options({ splits: 'all' })
+      .calculate({ $sum: '$amount' }),
+  });
+
+  let scheduleBalance = null;
+  let scheduleData = useCachedSchedules();
+  let schedules = scheduleData ? scheduleData.schedules : [];
+  let previewIds = [...selectedItems]
+    .filter(id => isPreviewId(id))
+    .map(id => id.slice(8));
+  for (let s of schedules) {
+    if (previewIds.includes(s.id)) {
+      if (!account || account.id === s._account) {
+        scheduleBalance += s._amount;
+      } else {
+        scheduleBalance -= s._amount;
+      }
+    }
+  }
+
+  if (balance == null) {
+    if (scheduleBalance == null) {
+      return null;
+    } else {
+      balance = scheduleBalance;
+    }
+  } else if (scheduleBalance != null) {
+    balance += scheduleBalance;
+  }
+
+  return <DetailedBalance name="Selected balance:" balance={balance} />;
+}
+
+function MoreBalances({ balanceQuery }) {
+  let cleared = useSheetValue({
+    name: balanceQuery.name + '-cleared',
+    query: balanceQuery.query.filter({ cleared: true }),
+  });
+  let uncleared = useSheetValue({
+    name: balanceQuery.name + '-uncleared',
+    query: balanceQuery.query.filter({ cleared: false }),
+  });
+
+  return (
+    <View style={{ flexDirection: 'row' }}>
+      <DetailedBalance name="Cleared total:" balance={cleared} />
+      <DetailedBalance name="Uncleared total:" balance={uncleared} />
+    </View>
+  );
+}
+
+export function Balances({
+  balanceQuery,
+  showExtraBalances,
+  onToggleExtraBalances,
+  account,
+}) {
+  let selectedItems = useSelectedItems();
+
+  return (
+    <View
+      style={{
+        flexDirection: 'row',
+        alignItems: 'center',
+        marginTop: -5,
+        marginLeft: -5,
+      }}
+    >
+      <Button
+        data-testid="account-balance"
+        bare
+        onClick={onToggleExtraBalances}
+        style={{
+          '& svg': {
+            opacity: selectedItems.size > 0 || showExtraBalances ? 1 : 0,
+          },
+          '&:hover svg': { opacity: 1 },
+        }}
+      >
+        <CellValue
+          binding={{ ...balanceQuery, value: 0 }}
+          type="financial"
+          style={{ fontSize: 22, fontWeight: 400 }}
+          getStyle={value => ({
+            color: value < 0 ? colors.r5 : value > 0 ? colors.g5 : colors.n8,
+          })}
+        />
+
+        <ArrowButtonRight1
+          style={{
+            width: 10,
+            height: 10,
+            marginLeft: 10,
+            color: colors.n5,
+            transform: showExtraBalances ? 'rotateZ(180deg)' : 'rotateZ(0)',
+          }}
+        />
+      </Button>
+      {showExtraBalances && <MoreBalances balanceQuery={balanceQuery} />}
+
+      {selectedItems.size > 0 && (
+        <SelectedBalance selectedItems={selectedItems} account={account} />
+      )}
+    </View>
+  );
+}
diff --git a/packages/desktop-client/src/components/accounts/Header.js b/packages/desktop-client/src/components/accounts/Header.js
new file mode 100644
index 0000000000000000000000000000000000000000..1a9033832c1cd3d47c9e0b60dbe80d3b07dca257
--- /dev/null
+++ b/packages/desktop-client/src/components/accounts/Header.js
@@ -0,0 +1,478 @@
+import React, { useState, useRef } from 'react';
+
+import useSyncServerStatus from '../../hooks/useSyncServerStatus';
+import Loading from '../../icons/AnimatedLoading';
+import Add from '../../icons/v1/Add';
+import ArrowsExpand3 from '../../icons/v2/ArrowsExpand3';
+import ArrowsShrink3 from '../../icons/v2/ArrowsShrink3';
+import DownloadThickBottom from '../../icons/v2/DownloadThickBottom';
+import Pencil1 from '../../icons/v2/Pencil1';
+import SvgRemove from '../../icons/v2/Remove';
+import SearchAlternate from '../../icons/v2/SearchAlternate';
+import { styles, colors } from '../../style';
+import AnimatedRefresh from '../AnimatedRefresh';
+import {
+  View,
+  Button,
+  MenuButton,
+  MenuTooltip,
+  Input,
+  InputWithContent,
+  InitialFocus,
+  Menu,
+  Stack,
+} from '../common';
+import { FilterButton } from '../filters/FiltersMenu';
+import { FiltersStack } from '../filters/SavedFilters';
+import { KeyHandlers } from '../KeyHandlers';
+import NotesButton from '../NotesButton';
+import { SelectedTransactionsButton } from '../transactions/SelectedTransactions';
+import { useSplitsExpanded } from '../transactions/TransactionsTable';
+
+import { Balances } from './Balance';
+import { ReconcilingMessage, ReconcileTooltip } from './Reconcile';
+
+export function AccountHeader({
+  tableRef,
+  editingName,
+  isNameEditable,
+  workingHard,
+  accountName,
+  account,
+  filterId,
+  filtersList,
+  accountsSyncing,
+  accounts,
+  transactions,
+  showBalances,
+  showExtraBalances,
+  showCleared,
+  showEmptyMessage,
+  balanceQuery,
+  reconcileAmount,
+  canCalculateBalance,
+  search,
+  filters,
+  conditionsOp,
+  savePrefs,
+  onSearch,
+  onAddTransaction,
+  onShowTransactions,
+  onDoneReconciling,
+  onCreateReconciliationTransaction,
+  onToggleExtraBalances,
+  onSaveName,
+  onExposeName,
+  onSync,
+  onImport,
+  onMenuSelect,
+  onReconcile,
+  onBatchDelete,
+  onBatchDuplicate,
+  onBatchEdit,
+  onBatchUnlink,
+  onCreateRule,
+  onApplyFilter,
+  onUpdateFilter,
+  onClearFilters,
+  onReloadSavedFilter,
+  onCondOpChange,
+  onDeleteFilter,
+  onScheduleAction,
+}) {
+  let [menuOpen, setMenuOpen] = useState(false);
+  let searchInput = useRef(null);
+  let splitsExpanded = useSplitsExpanded();
+
+  let canSync = account && account.account_id;
+  if (!account) {
+    // All accounts - check for any syncable account
+    canSync = !!accounts.find(account => !!account.account_id);
+  }
+
+  function onToggleSplits() {
+    if (tableRef.current) {
+      splitsExpanded.dispatch({
+        type: 'switch-mode',
+        id: tableRef.current.getScrolledItem(),
+      });
+
+      savePrefs({
+        'expand-splits': !(splitsExpanded.state.mode === 'expand'),
+      });
+    }
+  }
+
+  return (
+    <>
+      <KeyHandlers
+        keys={{
+          'ctrl+f, cmd+f': () => {
+            if (searchInput.current) {
+              searchInput.current.focus();
+            }
+          },
+        }}
+      />
+
+      <View style={[styles.pageContent, { paddingBottom: 10, flexShrink: 0 }]}>
+        <View style={{ marginTop: 2, alignItems: 'flex-start' }}>
+          <View>
+            {editingName ? (
+              <InitialFocus>
+                <Input
+                  defaultValue={accountName}
+                  onEnter={e => onSaveName(e.target.value)}
+                  onBlur={() => onExposeName(false)}
+                  style={{
+                    fontSize: 25,
+                    fontWeight: 500,
+                    marginTop: -5,
+                    marginBottom: -2,
+                    marginLeft: -5,
+                  }}
+                />
+              </InitialFocus>
+            ) : isNameEditable ? (
+              <View
+                style={{
+                  flexDirection: 'row',
+                  alignItems: 'center',
+                  gap: 3,
+                  '& .hover-visible': {
+                    opacity: 0,
+                    transition: 'opacity .25s',
+                  },
+                  '&:hover .hover-visible': {
+                    opacity: 1,
+                  },
+                }}
+              >
+                <View
+                  style={{
+                    fontSize: 25,
+                    fontWeight: 500,
+                    marginRight: 5,
+                    marginBottom: 5,
+                  }}
+                  data-testid="account-name"
+                >
+                  {account && account.closed
+                    ? 'Closed: ' + accountName
+                    : accountName}
+                </View>
+
+                {account && <NotesButton id={`account-${account.id}`} />}
+                <Button
+                  bare
+                  className="hover-visible"
+                  onClick={() => onExposeName(true)}
+                >
+                  <Pencil1
+                    style={{
+                      width: 11,
+                      height: 11,
+                      color: colors.n8,
+                    }}
+                  />
+                </Button>
+              </View>
+            ) : (
+              <View
+                style={{ fontSize: 25, fontWeight: 500, marginBottom: 5 }}
+                data-testid="account-name"
+              >
+                {account && account.closed
+                  ? 'Closed: ' + accountName
+                  : accountName}
+              </View>
+            )}
+          </View>
+        </View>
+
+        <Balances
+          balanceQuery={balanceQuery}
+          showExtraBalances={showExtraBalances}
+          onToggleExtraBalances={onToggleExtraBalances}
+          account={account}
+        />
+
+        <Stack
+          spacing={2}
+          direction="row"
+          align="center"
+          style={{ marginTop: 12 }}
+        >
+          {((account && !account.closed) || canSync) && (
+            <Button bare onClick={canSync ? onSync : onImport}>
+              {canSync ? (
+                <>
+                  <AnimatedRefresh
+                    width={13}
+                    height={13}
+                    animating={
+                      (account && accountsSyncing === account.name) ||
+                      accountsSyncing === '__all'
+                    }
+                    style={{ color: 'currentColor', marginRight: 4 }}
+                  />{' '}
+                  Sync
+                </>
+              ) : (
+                <>
+                  <DownloadThickBottom
+                    width={13}
+                    height={13}
+                    style={{ color: 'currentColor', marginRight: 4 }}
+                  />{' '}
+                  Import
+                </>
+              )}
+            </Button>
+          )}
+          {!showEmptyMessage && (
+            <Button bare onClick={onAddTransaction}>
+              <Add
+                width={10}
+                height={10}
+                style={{ color: 'inherit', marginRight: 3 }}
+              />{' '}
+              Add New
+            </Button>
+          )}
+          <View>
+            <FilterButton onApply={onApplyFilter} />
+          </View>
+          <InputWithContent
+            leftContent={
+              <SearchAlternate
+                style={{
+                  width: 13,
+                  height: 13,
+                  flexShrink: 0,
+                  color: search ? colors.p7 : 'inherit',
+                  margin: 5,
+                  marginRight: 0,
+                }}
+              />
+            }
+            rightContent={
+              search && (
+                <Button
+                  bare
+                  style={{ padding: 8 }}
+                  onClick={() => onSearch('')}
+                  title="Clear search term"
+                >
+                  <SvgRemove
+                    style={{
+                      width: 8,
+                      height: 8,
+                      color: 'inherit',
+                    }}
+                  />
+                </Button>
+              )
+            }
+            inputRef={searchInput}
+            value={search}
+            placeholder="Search"
+            onKeyDown={e => {
+              if (e.key === 'Escape') onSearch('');
+            }}
+            getStyle={focused => [
+              {
+                backgroundColor: 'transparent',
+                borderWidth: 0,
+                boxShadow: 'none',
+                transition: 'color .15s',
+                '& input::placeholder': {
+                  color: colors.n1,
+                  transition: 'color .25s',
+                },
+              },
+              focused && { boxShadow: '0 0 0 2px ' + colors.b5 },
+              !focused && search !== '' && { color: colors.p4 },
+            ]}
+            onChange={e => onSearch(e.target.value)}
+          />
+          {workingHard ? (
+            <View>
+              <Loading color={colors.n1} style={{ width: 16, height: 16 }} />
+            </View>
+          ) : (
+            <SelectedTransactionsButton
+              getTransaction={id => transactions.find(t => t.id === id)}
+              onShow={onShowTransactions}
+              onDuplicate={onBatchDuplicate}
+              onDelete={onBatchDelete}
+              onEdit={onBatchEdit}
+              onUnlink={onBatchUnlink}
+              onCreateRule={onCreateRule}
+              onScheduleAction={onScheduleAction}
+            />
+          )}
+          <Button
+            bare
+            disabled={search !== '' || filters.length > 0}
+            style={{ padding: 6 }}
+            onClick={onToggleSplits}
+            title={
+              splitsExpanded.state.mode === 'collapse'
+                ? 'Collapse split transactions'
+                : 'Expand split transactions'
+            }
+          >
+            {splitsExpanded.state.mode === 'collapse' ? (
+              <ArrowsShrink3
+                style={{
+                  width: 14,
+                  height: 14,
+                  color: 'inherit',
+                }}
+              />
+            ) : (
+              <ArrowsExpand3
+                style={{
+                  width: 14,
+                  height: 14,
+                  color: 'inherit',
+                }}
+              />
+            )}
+          </Button>
+          {account ? (
+            <View>
+              <MenuButton onClick={() => setMenuOpen(true)} />
+
+              {menuOpen && (
+                <AccountMenu
+                  account={account}
+                  canSync={canSync}
+                  canShowBalances={canCalculateBalance()}
+                  showBalances={showBalances}
+                  showCleared={showCleared}
+                  onMenuSelect={item => {
+                    setMenuOpen(false);
+                    onMenuSelect(item);
+                  }}
+                  onReconcile={onReconcile}
+                  onClose={() => setMenuOpen(false)}
+                />
+              )}
+            </View>
+          ) : (
+            <View>
+              <MenuButton onClick={() => setMenuOpen(true)} />
+
+              {menuOpen && (
+                <CategoryMenu
+                  onMenuSelect={item => {
+                    setMenuOpen(false);
+                    onMenuSelect(item);
+                  }}
+                  onClose={() => setMenuOpen(false)}
+                />
+              )}
+            </View>
+          )}
+        </Stack>
+
+        {filters && filters.length > 0 && (
+          <FiltersStack
+            filters={filters}
+            conditionsOp={conditionsOp}
+            onUpdateFilter={onUpdateFilter}
+            onDeleteFilter={onDeleteFilter}
+            onClearFilters={onClearFilters}
+            onReloadSavedFilter={onReloadSavedFilter}
+            filterId={filterId}
+            filtersList={filtersList}
+            onCondOpChange={onCondOpChange}
+          />
+        )}
+      </View>
+      {reconcileAmount != null && (
+        <ReconcilingMessage
+          targetBalance={reconcileAmount}
+          balanceQuery={balanceQuery}
+          onDone={onDoneReconciling}
+          onCreateTransaction={onCreateReconciliationTransaction}
+        />
+      )}
+    </>
+  );
+}
+
+function AccountMenu({
+  account,
+  canSync,
+  showBalances,
+  canShowBalances,
+  showCleared,
+  onClose,
+  onReconcile,
+  onMenuSelect,
+}) {
+  let [tooltip, setTooltip] = useState('default');
+  const syncServerStatus = useSyncServerStatus();
+
+  return tooltip === 'reconcile' ? (
+    <ReconcileTooltip
+      account={account}
+      onClose={onClose}
+      onReconcile={onReconcile}
+    />
+  ) : (
+    <MenuTooltip width={200} onClose={onClose}>
+      <Menu
+        onMenuSelect={item => {
+          if (item === 'reconcile') {
+            setTooltip('reconcile');
+          } else {
+            onMenuSelect(item);
+          }
+        }}
+        items={[
+          canShowBalances && {
+            name: 'toggle-balance',
+            text: (showBalances ? 'Hide' : 'Show') + ' Running Balance',
+          },
+          {
+            name: 'toggle-cleared',
+            text: (showCleared ? 'Hide' : 'Show') + ' “Cleared” Checkboxes',
+          },
+          { name: 'export', text: 'Export' },
+          { name: 'reconcile', text: 'Reconcile' },
+          account &&
+            !account.closed &&
+            (canSync
+              ? {
+                  name: 'unlink',
+                  text: 'Unlink Account',
+                }
+              : syncServerStatus === 'online' && {
+                  name: 'link',
+                  text: 'Link Account',
+                }),
+          account.closed
+            ? { name: 'reopen', text: 'Reopen Account' }
+            : { name: 'close', text: 'Close Account' },
+        ].filter(x => x)}
+      />
+    </MenuTooltip>
+  );
+}
+
+function CategoryMenu({ onClose, onMenuSelect }) {
+  return (
+    <MenuTooltip width={200} onClose={onClose}>
+      <Menu
+        onMenuSelect={item => {
+          onMenuSelect(item);
+        }}
+        items={[{ name: 'export', text: 'Export' }]}
+      />
+    </MenuTooltip>
+  );
+}
diff --git a/packages/desktop-client/src/components/accounts/MobileAccountDetails.js b/packages/desktop-client/src/components/accounts/MobileAccountDetails.js
index 49c99b0c713241b2930f1d5f04a6cb14f0ad1feb..3c6da2a63ee279d643f82814b091486c8975e1ea 100644
--- a/packages/desktop-client/src/components/accounts/MobileAccountDetails.js
+++ b/packages/desktop-client/src/components/accounts/MobileAccountDetails.js
@@ -8,8 +8,7 @@ import { colors, styles } from '../../style';
 import { Button, InputWithContent, Label, View } from '../common';
 import Text from '../common/Text';
 import CellValue from '../spreadsheet/CellValue';
-
-import { TransactionList } from './MobileTransaction';
+import { TransactionList } from '../transactions/MobileTransaction';
 
 function TransactionSearchInput({ accountName, onSearch }) {
   const [text, setText] = useState('');
diff --git a/packages/desktop-client/src/components/accounts/Reconcile.js b/packages/desktop-client/src/components/accounts/Reconcile.js
new file mode 100644
index 0000000000000000000000000000000000000000..b542d9520ec7e677af1639498deb3be9da04e399
--- /dev/null
+++ b/packages/desktop-client/src/components/accounts/Reconcile.js
@@ -0,0 +1,128 @@
+import React from 'react';
+
+import * as queries from 'loot-core/src/client/queries';
+import { currencyToInteger } from 'loot-core/src/shared/util';
+
+import CheckCircle1 from '../../icons/v2/CheckCircle1';
+import { styles, colors } from '../../style';
+import { View, Text, Button, Input, InitialFocus, Tooltip } from '../common';
+import format from '../spreadsheet/format';
+import useSheetValue from '../spreadsheet/useSheetValue';
+
+export function ReconcilingMessage({
+  balanceQuery,
+  targetBalance,
+  onDone,
+  onCreateTransaction,
+}) {
+  let cleared = useSheetValue({
+    name: balanceQuery.name + '-cleared',
+    value: 0,
+    query: balanceQuery.query.filter({ cleared: true }),
+  });
+  let targetDiff = targetBalance - cleared;
+
+  return (
+    <View
+      style={{
+        flexDirection: 'row',
+        alignSelf: 'center',
+        backgroundColor: 'white',
+        ...styles.shadow,
+        borderRadius: 4,
+        marginTop: 5,
+        marginBottom: 15,
+        padding: 10,
+      }}
+    >
+      <View style={{ flexDirection: 'row', alignItems: 'center' }}>
+        {targetDiff === 0 ? (
+          <View
+            style={{
+              color: colors.g4,
+              flex: 1,
+              flexDirection: 'row',
+              alignItems: 'center',
+              justifyContent: 'center',
+            }}
+          >
+            <CheckCircle1
+              style={{
+                width: 13,
+                height: 13,
+                color: colors.g5,
+                marginRight: 3,
+              }}
+            />
+            All reconciled!
+          </View>
+        ) : (
+          <View style={{ color: colors.n3 }}>
+            <Text style={{ fontStyle: 'italic', textAlign: 'center' }}>
+              Your cleared balance{' '}
+              <strong>{format(cleared, 'financial')}</strong> needs{' '}
+              <strong>
+                {(targetDiff > 0 ? '+' : '') + format(targetDiff, 'financial')}
+              </strong>{' '}
+              to match
+              <br /> your bank’s balance of{' '}
+              <Text style={{ fontWeight: 700 }}>
+                {format(targetBalance, 'financial')}
+              </Text>
+            </Text>
+          </View>
+        )}
+        <View style={{ marginLeft: 15 }}>
+          <Button primary onClick={onDone}>
+            Done Reconciling
+          </Button>
+        </View>
+        {targetDiff !== 0 && (
+          <View style={{ marginLeft: 15 }}>
+            <Button onClick={() => onCreateTransaction(targetDiff)}>
+              Create Reconciliation Transaction
+            </Button>
+          </View>
+        )}
+      </View>
+    </View>
+  );
+}
+
+export function ReconcileTooltip({ account, onReconcile, onClose }) {
+  let balance = useSheetValue(queries.accountBalance(account));
+
+  function onSubmit(e) {
+    e.preventDefault();
+    let input = e.target.elements[0];
+    let amount = currencyToInteger(input.value);
+    if (amount != null) {
+      onReconcile(amount == null ? balance : amount);
+      onClose();
+    } else {
+      input.select();
+    }
+  }
+
+  return (
+    <Tooltip position="bottom-right" width={275} onClose={onClose}>
+      <View style={{ padding: '5px 8px' }}>
+        <Text>
+          Enter the current balance of your bank account that you want to
+          reconcile with:
+        </Text>
+        <form onSubmit={onSubmit}>
+          {balance != null && (
+            <InitialFocus>
+              <Input
+                defaultValue={format(balance, 'financial')}
+                style={{ margin: '7px 0' }}
+              />
+            </InitialFocus>
+          )}
+          <Button primary>Reconcile</Button>
+        </form>
+      </View>
+    </Tooltip>
+  );
+}
diff --git a/packages/desktop-client/src/components/common.tsx b/packages/desktop-client/src/components/common.tsx
index d63d8233195f1c9487c3a211eb22228aedc13fa7..0b24fb651c2efe0e00b7181300dad75de34b3d83 100644
--- a/packages/desktop-client/src/components/common.tsx
+++ b/packages/desktop-client/src/components/common.tsx
@@ -28,6 +28,8 @@ export { default as Input } from './common/Input';
 export { default as InputWithContent } from './common/InputWithContent';
 export { default as Label } from './common/Label';
 export { default as Menu } from './common/Menu';
+export { default as MenuButton } from './common/MenuButton';
+export { default as MenuTooltip } from './common/MenuTooltip';
 export { default as Modal, ModalButtons } from './common/Modal';
 export { default as Search } from './common/Search';
 export { default as Select } from './common/Select';
diff --git a/packages/desktop-client/src/components/common/MenuButton.tsx b/packages/desktop-client/src/components/common/MenuButton.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..bda660c790f71de085b888896124df36ad70681f
--- /dev/null
+++ b/packages/desktop-client/src/components/common/MenuButton.tsx
@@ -0,0 +1,17 @@
+import React from 'react';
+
+import DotsHorizontalTriple from '../../icons/v1/DotsHorizontalTriple';
+
+import Button from './Button';
+
+export default function MenuButton({ onClick }) {
+  return (
+    <Button bare onClick={onClick} aria-label="Menu">
+      <DotsHorizontalTriple
+        width={15}
+        height={15}
+        style={{ color: 'inherit', transform: 'rotateZ(90deg)' }}
+      />
+    </Button>
+  );
+}
diff --git a/packages/desktop-client/src/components/common/MenuTooltip.tsx b/packages/desktop-client/src/components/common/MenuTooltip.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..7549da2ceb386ed0adaf5b3a15b28f7c5e1000e9
--- /dev/null
+++ b/packages/desktop-client/src/components/common/MenuTooltip.tsx
@@ -0,0 +1,16 @@
+import React from 'react';
+
+import { Tooltip } from '../common';
+
+export default function MenuTooltip({ width, onClose, children }) {
+  return (
+    <Tooltip
+      position="bottom-right"
+      width={width}
+      style={{ padding: 0 }}
+      onClose={onClose}
+    >
+      {children}
+    </Tooltip>
+  );
+}
diff --git a/packages/desktop-client/src/components/filters/SavedFilters.js b/packages/desktop-client/src/components/filters/SavedFilters.js
index a243cf8f4b3f6bf2c305b8de0701f3a920a5208c..eff68869058220053ddb95e46bdc203abb5ec170 100644
--- a/packages/desktop-client/src/components/filters/SavedFilters.js
+++ b/packages/desktop-client/src/components/filters/SavedFilters.js
@@ -4,8 +4,7 @@ import { send, sendCatch } from 'loot-core/src/platform/client/fetch';
 
 import ExpandArrow from '../../icons/v0/ExpandArrow';
 import { colors } from '../../style';
-import { MenuTooltip } from '../accounts/Account';
-import { View, Text, Button, Menu, Stack } from '../common';
+import { View, Text, Button, Menu, MenuTooltip, Stack } from '../common';
 import { FormField, FormLabel } from '../forms';
 import { FieldSelect } from '../modals/EditRule';
 import GenericInput from '../util/GenericInput';
diff --git a/packages/desktop-client/src/components/modals/EditRule.js b/packages/desktop-client/src/components/modals/EditRule.js
index bfb2594218b76a0ef07ee34a55cb4a9b1910dce7..f949e99f3e9191baf8cb69891aca44dad7427175 100644
--- a/packages/desktop-client/src/components/modals/EditRule.js
+++ b/packages/desktop-client/src/components/modals/EditRule.js
@@ -30,7 +30,6 @@ import AddIcon from '../../icons/v0/Add';
 import SubtractIcon from '../../icons/v0/Subtract';
 import InformationOutline from '../../icons/v1/InformationOutline';
 import { colors } from '../../style';
-import SimpleTransactionsTable from '../accounts/SimpleTransactionsTable';
 import {
   View,
   Text,
@@ -41,6 +40,7 @@ import {
   Tooltip,
 } from '../common';
 import { StatusBadge } from '../schedules/StatusBadge';
+import SimpleTransactionsTable from '../transactions/SimpleTransactionsTable';
 import { BetweenAmountInput } from '../util/AmountInput';
 import DisplayId from '../util/DisplayId';
 import GenericInput from '../util/GenericInput';
diff --git a/packages/desktop-client/src/components/schedules/EditSchedule.js b/packages/desktop-client/src/components/schedules/EditSchedule.js
index 32bd37231d9bccc06fb854cf587a0a9455872f45..8a9176e976f2d37e6bf1341f58e785e41def3439 100644
--- a/packages/desktop-client/src/components/schedules/EditSchedule.js
+++ b/packages/desktop-client/src/components/schedules/EditSchedule.js
@@ -11,7 +11,6 @@ import { extractScheduleConds } from 'loot-core/src/shared/schedules';
 
 import useSelected, { SelectedProvider } from '../../hooks/useSelected';
 import { colors } from '../../style';
-import SimpleTransactionsTable from '../accounts/SimpleTransactionsTable';
 import AccountAutocomplete from '../autocomplete/AccountAutocomplete';
 import PayeeAutocomplete from '../autocomplete/PayeeAutocomplete';
 import { Stack, View, Text, Button } from '../common';
@@ -21,6 +20,7 @@ import { Page } from '../Page';
 import DateSelect from '../select/DateSelect';
 import RecurringSchedulePicker from '../select/RecurringSchedulePicker';
 import { SelectedItemsButton } from '../table';
+import SimpleTransactionsTable from '../transactions/SimpleTransactionsTable';
 import { AmountInput, BetweenAmountInput } from '../util/AmountInput';
 import GenericInput from '../util/GenericInput';
 
diff --git a/packages/desktop-client/src/components/accounts/MobileTransaction.js b/packages/desktop-client/src/components/transactions/MobileTransaction.js
similarity index 100%
rename from packages/desktop-client/src/components/accounts/MobileTransaction.js
rename to packages/desktop-client/src/components/transactions/MobileTransaction.js
diff --git a/packages/desktop-client/src/components/transactions/SelectedTransactions.js b/packages/desktop-client/src/components/transactions/SelectedTransactions.js
new file mode 100644
index 0000000000000000000000000000000000000000..85195b29c925d49b836df9473c05dc05e430a8c5
--- /dev/null
+++ b/packages/desktop-client/src/components/transactions/SelectedTransactions.js
@@ -0,0 +1,153 @@
+import React, { useMemo } from 'react';
+
+import { useSelectedItems } from '../../hooks/useSelected';
+import { usePushModal } from '../../util/router-tools';
+import { Menu } from '../common';
+import { SelectedItemsButton } from '../table';
+
+import { isPreviewId } from './TransactionsTable';
+
+export function SelectedTransactionsButton({
+  getTransaction,
+  onShow,
+  onDuplicate,
+  onDelete,
+  onEdit,
+  onUnlink,
+  onCreateRule,
+  onScheduleAction,
+}) {
+  let pushModal = usePushModal();
+  let selectedItems = useSelectedItems();
+
+  let types = useMemo(() => {
+    let items = [...selectedItems];
+    return {
+      preview: !!items.find(id => isPreviewId(id)),
+      trans: !!items.find(id => !isPreviewId(id)),
+    };
+  }, [selectedItems]);
+
+  let ambiguousDuplication = useMemo(() => {
+    let transactions = [...selectedItems].map(id => getTransaction(id));
+
+    return transactions.some(t => t && t.is_child);
+  }, [selectedItems]);
+
+  let linked = useMemo(() => {
+    return (
+      !types.preview &&
+      [...selectedItems].every(id => {
+        let t = getTransaction(id);
+        return t && t.schedule;
+      })
+    );
+  }, [types.preview, selectedItems, getTransaction]);
+
+  return (
+    <SelectedItemsButton
+      name="transactions"
+      keyHandlers={
+        types.trans && {
+          f: () => onShow([...selectedItems]),
+          d: () => onDelete([...selectedItems]),
+          a: () => onEdit('account', [...selectedItems]),
+          p: () => onEdit('payee', [...selectedItems]),
+          n: () => onEdit('notes', [...selectedItems]),
+          c: () => onEdit('category', [...selectedItems]),
+          l: () => onEdit('cleared', [...selectedItems]),
+        }
+      }
+      items={[
+        ...(!types.trans
+          ? [
+              { name: 'view-schedule', text: 'View schedule' },
+              { name: 'post-transaction', text: 'Post transaction' },
+              { name: 'skip', text: 'Skip scheduled date' },
+            ]
+          : [
+              { name: 'show', text: 'Show', key: 'F' },
+              {
+                name: 'duplicate',
+                text: 'Duplicate',
+                disabled: ambiguousDuplication,
+              },
+              { name: 'delete', text: 'Delete', key: 'D' },
+              ...(linked
+                ? [
+                    {
+                      name: 'view-schedule',
+                      text: 'View schedule',
+                      disabled: selectedItems.size > 1,
+                    },
+                    { name: 'unlink-schedule', text: 'Unlink schedule' },
+                  ]
+                : [
+                    {
+                      name: 'link-schedule',
+                      text: 'Link schedule',
+                    },
+                    {
+                      name: 'create-rule',
+                      text: 'Create rule',
+                    },
+                  ]),
+              Menu.line,
+              { type: Menu.label, name: 'Edit field' },
+              { name: 'date', text: 'Date' },
+              { name: 'account', text: 'Account', key: 'A' },
+              { name: 'payee', text: 'Payee', key: 'P' },
+              { name: 'notes', text: 'Notes', key: 'N' },
+              { name: 'category', text: 'Category', key: 'C' },
+              { name: 'amount', text: 'Amount' },
+              { name: 'cleared', text: 'Cleared', key: 'L' },
+            ]),
+      ]}
+      onSelect={name => {
+        switch (name) {
+          case 'show':
+            onShow([...selectedItems]);
+            break;
+          case 'duplicate':
+            onDuplicate([...selectedItems]);
+            break;
+          case 'delete':
+            onDelete([...selectedItems]);
+            break;
+          case 'post-transaction':
+          case 'skip':
+            onScheduleAction(name, selectedItems);
+            break;
+          case 'view-schedule':
+            let firstId = [...selectedItems][0];
+            let scheduleId;
+            if (isPreviewId(firstId)) {
+              let parts = firstId.split('/');
+              scheduleId = parts[1];
+            } else {
+              let trans = getTransaction(firstId);
+              scheduleId = trans && trans.schedule;
+            }
+
+            if (scheduleId) {
+              pushModal(`/schedule/edit/${scheduleId}`);
+            }
+            break;
+          case 'link-schedule':
+            pushModal('/schedule/link', {
+              transactionIds: [...selectedItems],
+            });
+            break;
+          case 'unlink-schedule':
+            onUnlink([...selectedItems]);
+            break;
+          case 'create-rule':
+            onCreateRule([...selectedItems]);
+            break;
+          default:
+            onEdit(name, [...selectedItems]);
+        }
+      }}
+    ></SelectedItemsButton>
+  );
+}
diff --git a/packages/desktop-client/src/components/accounts/SimpleTransactionsTable.js b/packages/desktop-client/src/components/transactions/SimpleTransactionsTable.js
similarity index 100%
rename from packages/desktop-client/src/components/accounts/SimpleTransactionsTable.js
rename to packages/desktop-client/src/components/transactions/SimpleTransactionsTable.js
diff --git a/packages/desktop-client/src/components/accounts/TransactionList.js b/packages/desktop-client/src/components/transactions/TransactionList.js
similarity index 100%
rename from packages/desktop-client/src/components/accounts/TransactionList.js
rename to packages/desktop-client/src/components/transactions/TransactionList.js
diff --git a/packages/desktop-client/src/components/accounts/TransactionsTable.js b/packages/desktop-client/src/components/transactions/TransactionsTable.js
similarity index 100%
rename from packages/desktop-client/src/components/accounts/TransactionsTable.js
rename to packages/desktop-client/src/components/transactions/TransactionsTable.js
diff --git a/packages/desktop-client/src/components/accounts/TransactionsTable.test.js b/packages/desktop-client/src/components/transactions/TransactionsTable.test.js
similarity index 100%
rename from packages/desktop-client/src/components/accounts/TransactionsTable.test.js
rename to packages/desktop-client/src/components/transactions/TransactionsTable.test.js
diff --git a/upcoming-release-notes/1258.md b/upcoming-release-notes/1258.md
new file mode 100644
index 0000000000000000000000000000000000000000..a33a944d149c497e167b7e708b4be8a86f8c424b
--- /dev/null
+++ b/upcoming-release-notes/1258.md
@@ -0,0 +1,6 @@
+---
+category: Maintenance
+authors: [carkom]
+---
+
+Reorganized accounts directory. Pulled our Header functions to make the accounts.js smaller and more manageable.
\ No newline at end of file