diff --git a/packages/desktop-client/src/components/LoggedInUser.tsx b/packages/desktop-client/src/components/LoggedInUser.tsx
index f1043b764db27d5aa12b18709a9a067d4b6c19dc..c9eba0badb8517bd6f02ca2323debb1241aac2c3 100644
--- a/packages/desktop-client/src/components/LoggedInUser.tsx
+++ b/packages/desktop-client/src/components/LoggedInUser.tsx
@@ -1,5 +1,5 @@
 // @ts-strict-ignore
-import React, { useState, useEffect } from 'react';
+import React, { useState, useEffect, useRef } from 'react';
 import { useSelector } from 'react-redux';
 
 import { type State } from 'loot-core/src/client/state-types';
@@ -9,10 +9,10 @@ import { theme, styles, type CSSProperties } from '../style';
 
 import { Button } from './common/Button';
 import { Menu } from './common/Menu';
+import { Popover } from './common/Popover';
 import { Text } from './common/Text';
 import { View } from './common/View';
 import { useServerURL } from './ServerContext';
-import { Tooltip } from './tooltips';
 
 type LoggedInUserProps = {
   hideIfNoServer?: boolean;
@@ -29,6 +29,7 @@ export function LoggedInUser({
   const [loading, setLoading] = useState(true);
   const [menuOpen, setMenuOpen] = useState(false);
   const serverUrl = useServerURL();
+  const triggerRef = useRef(null);
 
   useEffect(() => {
     getUserData().then(() => setLoading(false));
@@ -95,6 +96,7 @@ export function LoggedInUser({
   return (
     <View style={{ flexDirection: 'row', alignItems: 'center', ...style }}>
       <Button
+        ref={triggerRef}
         type="bare"
         onClick={() => setMenuOpen(true)}
         style={color && { color }}
@@ -102,29 +104,27 @@ export function LoggedInUser({
         {serverMessage()}
       </Button>
 
-      {menuOpen && (
-        <Tooltip
-          position="bottom-right"
-          style={{ padding: 0 }}
-          onClose={() => setMenuOpen(false)}
-        >
-          <Menu
-            onMenuSelect={onMenuSelect}
-            items={[
-              serverUrl &&
-                !userData?.offline && {
-                  name: 'change-password',
-                  text: 'Change password',
-                },
-              serverUrl && { name: 'sign-out', text: 'Sign out' },
-              {
-                name: 'config-server',
-                text: serverUrl ? 'Change server URL' : 'Start using a server',
+      <Popover
+        triggerRef={triggerRef}
+        isOpen={menuOpen}
+        onOpenChange={() => setMenuOpen(false)}
+      >
+        <Menu
+          onMenuSelect={onMenuSelect}
+          items={[
+            serverUrl &&
+              !userData?.offline && {
+                name: 'change-password',
+                text: 'Change password',
               },
-            ]}
-          />
-        </Tooltip>
-      )}
+            serverUrl && { name: 'sign-out', text: 'Sign out' },
+            {
+              name: 'config-server',
+              text: serverUrl ? 'Change server URL' : 'Start using a server',
+            },
+          ]}
+        />
+      </Popover>
     </View>
   );
 }
diff --git a/packages/desktop-client/src/components/NotesButton.tsx b/packages/desktop-client/src/components/NotesButton.tsx
index 31868f52120c1f912c0f57a38b050cfacad5df28..f39af29506a5b17fe773223318b01f1ee188bcf7 100644
--- a/packages/desktop-client/src/components/NotesButton.tsx
+++ b/packages/desktop-client/src/components/NotesButton.tsx
@@ -1,5 +1,4 @@
 import React, { useEffect, useRef, useState, type ComponentProps } from 'react';
-import { Popover } from 'react-aria-components';
 
 import { useLiveQuery } from 'loot-core/src/client/query-hooks';
 import { send } from 'loot-core/src/platform/client/fetch';
@@ -7,9 +6,10 @@ import { q } from 'loot-core/src/shared/query';
 import { type NoteEntity } from 'loot-core/types/models';
 
 import { SvgCustomNotesPaper } from '../icons/v2';
-import { type CSSProperties, styles, theme } from '../style';
+import { type CSSProperties, theme } from '../style';
 
 import { Button } from './common/Button';
+import { Popover } from './common/Popover';
 import { Tooltip } from './common/Tooltip';
 import { View } from './common/View';
 import { Notes } from './Notes';
@@ -81,7 +81,7 @@ export function NotesButton({
         isOpen={isOpen}
         onOpenChange={onClose}
         placement={tooltipPosition}
-        style={{ ...styles.tooltip, marginTop: -8 }}
+        style={{ padding: 4 }}
       >
         <Notes notes={tempNotes} editable focused onChange={setTempNotes} />
       </Popover>
diff --git a/packages/desktop-client/src/components/ThemeSelector.tsx b/packages/desktop-client/src/components/ThemeSelector.tsx
index ed2a49508a213fbefcbcb1debcae32986e9589bc..1127ec128bc0b1171f305c70801c1c546c28a918 100644
--- a/packages/desktop-client/src/components/ThemeSelector.tsx
+++ b/packages/desktop-client/src/components/ThemeSelector.tsx
@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import React, { useRef, useState } from 'react';
 
 import type { Theme } from 'loot-core/src/types/prefs';
 
@@ -8,7 +8,7 @@ import { type CSSProperties, themeOptions, useTheme } from '../style';
 
 import { Button } from './common/Button';
 import { Menu } from './common/Menu';
-import { Tooltip } from './tooltips';
+import { Popover } from './common/Popover';
 
 type ThemeSelectorProps = {
   style?: CSSProperties;
@@ -17,6 +17,7 @@ type ThemeSelectorProps = {
 export function ThemeSelector({ style }: ThemeSelectorProps) {
   const [theme, switchTheme] = useTheme();
   const [menuOpen, setMenuOpen] = useState(false);
+  const triggerRef = useRef(null);
 
   const { isNarrowWidth } = useResponsive();
 
@@ -34,26 +35,32 @@ export function ThemeSelector({ style }: ThemeSelectorProps) {
 
   const Icon = themeIcons[theme] || SvgSun;
 
-  return isNarrowWidth ? null : (
-    <Button
-      type="bare"
-      aria-label="Switch theme"
-      onClick={() => setMenuOpen(true)}
-      style={style}
-    >
-      <Icon style={{ width: 13, height: 13, color: 'inherit' }} />
-      {menuOpen && (
-        <Tooltip
-          position="bottom-right"
-          style={{ padding: 0 }}
-          onClose={() => setMenuOpen(false)}
-        >
-          <Menu
-            onMenuSelect={onMenuSelect}
-            items={themeOptions.map(([name, text]) => ({ name, text }))}
-          />
-        </Tooltip>
-      )}
-    </Button>
+  if (isNarrowWidth) {
+    return null;
+  }
+
+  return (
+    <>
+      <Button
+        ref={triggerRef}
+        type="bare"
+        aria-label="Switch theme"
+        onClick={() => setMenuOpen(true)}
+        style={style}
+      >
+        <Icon style={{ width: 13, height: 13, color: 'inherit' }} />
+      </Button>
+
+      <Popover
+        triggerRef={triggerRef}
+        isOpen={menuOpen}
+        onOpenChange={() => setMenuOpen(false)}
+      >
+        <Menu
+          onMenuSelect={onMenuSelect}
+          items={themeOptions.map(([name, text]) => ({ name, text }))}
+        />
+      </Popover>
+    </>
   );
 }
diff --git a/packages/desktop-client/src/components/Titlebar.tsx b/packages/desktop-client/src/components/Titlebar.tsx
index 1d91cbc247e6f93e3b8559c2694c32a8122a4a7a..10d4ead37151ecba7ac68508c752cc43f051642e 100644
--- a/packages/desktop-client/src/components/Titlebar.tsx
+++ b/packages/desktop-client/src/components/Titlebar.tsx
@@ -35,6 +35,7 @@ import { MonthCountSelector } from './budget/MonthCountSelector';
 import { Button, ButtonWithLoading } from './common/Button';
 import { Link } from './common/Link';
 import { Paragraph } from './common/Paragraph';
+import { Popover } from './common/Popover';
 import { Text } from './common/Text';
 import { View } from './common/View';
 import { LoggedInUser } from './LoggedInUser';
@@ -42,7 +43,6 @@ import { useServerURL } from './ServerContext';
 import { useSidebar } from './sidebar/SidebarProvider';
 import { useSheetValue } from './spreadsheet/useSheetValue';
 import { ThemeSelector } from './ThemeSelector';
-import { Tooltip } from './tooltips';
 
 export const SWITCH_BUDGET_MESSAGE_TYPE = 'budget/switch-type';
 
@@ -290,7 +290,8 @@ function BudgetTitlebar() {
   const { sendEvent } = useContext(TitlebarContext);
 
   const [loading, setLoading] = useState(false);
-  const [showTooltip, setShowTooltip] = useState(false);
+  const [showPopover, setShowPopover] = useState(false);
+  const triggerRef = useRef(null);
 
   const reportBudgetEnabled = useFeatureFlag('reportBudget');
 
@@ -320,6 +321,7 @@ function BudgetTitlebar() {
       {reportBudgetEnabled && (
         <View style={{ marginLeft: -5 }}>
           <ButtonWithLoading
+            ref={triggerRef}
             type="bare"
             loading={loading}
             style={{
@@ -327,52 +329,48 @@ function BudgetTitlebar() {
               padding: '4px 7px',
             }}
             title="Learn more about budgeting"
-            onClick={() => setShowTooltip(true)}
+            onClick={() => setShowPopover(true)}
           >
             {budgetType === 'report' ? 'Report budget' : 'Rollover budget'}
           </ButtonWithLoading>
-          {showTooltip && (
-            <Tooltip
-              position="bottom-left"
-              onClose={() => setShowTooltip(false)}
-              style={{
-                padding: 10,
-                maxWidth: 400,
-              }}
-            >
-              <Paragraph>
-                You are currently using a{' '}
-                <Text style={{ fontWeight: 600 }}>
-                  {budgetType === 'report'
-                    ? 'Report budget'
-                    : 'Rollover budget'}
-                  .
-                </Text>{' '}
-                Switching will not lose any data and you can always switch back.
-              </Paragraph>
-              <Paragraph>
-                <ButtonWithLoading
-                  type="primary"
-                  loading={loading}
-                  onClick={onSwitchType}
-                >
-                  Switch to a{' '}
-                  {budgetType === 'report'
-                    ? 'Rollover budget'
-                    : 'Report budget'}
-                </ButtonWithLoading>
-              </Paragraph>
-              <Paragraph isLast={true}>
-                <Link
-                  variant="external"
-                  to="https://actualbudget.org/docs/experimental/report-budget"
-                  linkColor="muted"
-                >
-                  How do these types of budgeting work?
-                </Link>
-              </Paragraph>
-            </Tooltip>
-          )}
+
+          <Popover
+            triggerRef={triggerRef}
+            placement="bottom start"
+            isOpen={showPopover}
+            onOpenChange={() => setShowPopover(false)}
+            style={{
+              padding: 10,
+              maxWidth: 400,
+            }}
+          >
+            <Paragraph>
+              You are currently using a{' '}
+              <Text style={{ fontWeight: 600 }}>
+                {budgetType === 'report' ? 'Report budget' : 'Rollover budget'}.
+              </Text>{' '}
+              Switching will not lose any data and you can always switch back.
+            </Paragraph>
+            <Paragraph>
+              <ButtonWithLoading
+                type="primary"
+                loading={loading}
+                onClick={onSwitchType}
+              >
+                Switch to a{' '}
+                {budgetType === 'report' ? 'Rollover budget' : 'Report budget'}
+              </ButtonWithLoading>
+            </Paragraph>
+            <Paragraph isLast={true}>
+              <Link
+                variant="external"
+                to="https://actualbudget.org/docs/experimental/report-budget"
+                linkColor="muted"
+              >
+                How do these types of budgeting work?
+              </Link>
+            </Paragraph>
+          </Popover>
         </View>
       )}
     </View>
diff --git a/packages/desktop-client/src/components/accounts/AccountSyncCheck.jsx b/packages/desktop-client/src/components/accounts/AccountSyncCheck.jsx
index f253a51f162639249af21837e4dea5a882fd6537..6778992340c2f29829f60dc02dab38a10fa3bedd 100644
--- a/packages/desktop-client/src/components/accounts/AccountSyncCheck.jsx
+++ b/packages/desktop-client/src/components/accounts/AccountSyncCheck.jsx
@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import React, { useRef, useState } from 'react';
 import { useSelector } from 'react-redux';
 import { useParams } from 'react-router-dom';
 
@@ -9,8 +9,8 @@ import { SvgExclamationOutline } from '../../icons/v1';
 import { theme } from '../../style';
 import { Button } from '../common/Button';
 import { Link } from '../common/Link';
+import { Popover } from '../common/Popover';
 import { View } from '../common/View';
-import { Tooltip } from '../tooltips';
 
 function getErrorMessage(type, code) {
   switch (type.toUpperCase()) {
@@ -56,6 +56,8 @@ export function AccountSyncCheck() {
 
   const { id } = useParams();
   const [open, setOpen] = useState(false);
+  const triggerRef = useRef(null);
+
   if (!failedAccounts) {
     return null;
   }
@@ -85,6 +87,7 @@ export function AccountSyncCheck() {
   return (
     <View>
       <Button
+        ref={triggerRef}
         type="bare"
         style={{
           flexDirection: 'row',
@@ -102,38 +105,34 @@ export function AccountSyncCheck() {
         This account is experiencing connection problems. Let’s fix it.
       </Button>
 
-      {open && (
-        <Tooltip
-          position="bottom-left"
-          onClose={() => setOpen(false)}
-          style={{ fontSize: 14, padding: 15, maxWidth: 400 }}
-        >
-          <div style={{ marginBottom: '1.15em' }}>
-            The server returned the following error:
-          </div>
-
-          <div style={{ marginBottom: '1.25em', color: theme.errorText }}>
-            {getErrorMessage(error.type, error.code)}
-          </div>
-
-          <View style={{ justifyContent: 'flex-end', flexDirection: 'row' }}>
-            {showAuth ? (
-              <>
-                <Button onClick={unlink}>Unlink</Button>
-                <Button
-                  type="primary"
-                  onClick={reauth}
-                  style={{ marginLeft: 5 }}
-                >
-                  Reauthorize
-                </Button>
-              </>
-            ) : (
-              <Button onClick={unlink}>Unlink account</Button>
-            )}
-          </View>
-        </Tooltip>
-      )}
+      <Popover
+        triggerRef={triggerRef}
+        placement="bottom start"
+        isOpen={open}
+        onOpenChange={() => setOpen(false)}
+        style={{ fontSize: 14, padding: 15, maxWidth: 400 }}
+      >
+        <div style={{ marginBottom: '1.15em' }}>
+          The server returned the following error:
+        </div>
+
+        <div style={{ marginBottom: '1.25em', color: theme.errorText }}>
+          {getErrorMessage(error.type, error.code)}
+        </div>
+
+        <View style={{ justifyContent: 'flex-end', flexDirection: 'row' }}>
+          {showAuth ? (
+            <>
+              <Button onClick={unlink}>Unlink</Button>
+              <Button type="primary" onClick={reauth} style={{ marginLeft: 5 }}>
+                Reauthorize
+              </Button>
+            </>
+          ) : (
+            <Button onClick={unlink}>Unlink account</Button>
+          )}
+        </View>
+      </Popover>
     </View>
   );
 }
diff --git a/packages/desktop-client/src/components/common/Popover.tsx b/packages/desktop-client/src/components/common/Popover.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..94b029f74510de7bc317bffbbfd045d75cd7265a
--- /dev/null
+++ b/packages/desktop-client/src/components/common/Popover.tsx
@@ -0,0 +1,17 @@
+import { type ComponentProps } from 'react';
+import { Popover as ReactAriaPopover } from 'react-aria-components';
+
+import { styles } from '../../style';
+
+type PopoverProps = ComponentProps<typeof ReactAriaPopover>;
+
+export const Popover = ({ style = {}, ...props }: PopoverProps) => {
+  return (
+    <ReactAriaPopover
+      placement="bottom end"
+      offset={0}
+      style={{ ...styles.tooltip, padding: 0, ...style }}
+      {...props}
+    />
+  );
+};
diff --git a/packages/desktop-client/src/components/sidebar/Sidebar.tsx b/packages/desktop-client/src/components/sidebar/Sidebar.tsx
index bd6bc5335f4d80ea0e99e0028d5be731af39d817..77e863ccf18d3f9166ab82a6b37a536299b059d6 100644
--- a/packages/desktop-client/src/components/sidebar/Sidebar.tsx
+++ b/packages/desktop-client/src/components/sidebar/Sidebar.tsx
@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import React, { useRef, useState } from 'react';
 import { useDispatch } from 'react-redux';
 
 import {
@@ -20,9 +20,9 @@ import { Button } from '../common/Button';
 import { InitialFocus } from '../common/InitialFocus';
 import { Input } from '../common/Input';
 import { Menu } from '../common/Menu';
+import { Popover } from '../common/Popover';
 import { Text } from '../common/Text';
 import { View } from '../common/View';
-import { Tooltip } from '../tooltips';
 
 import { Accounts } from './Accounts';
 import { Item } from './Item';
@@ -145,6 +145,7 @@ function EditableBudgetName() {
   const [budgetName, setBudgetNamePref] = useLocalPref('budgetName');
   const [editing, setEditing] = useState(false);
   const [menuOpen, setMenuOpen] = useState(false);
+  const triggerRef = useRef(null);
 
   function onMenuSelect(type: string) {
     setMenuOpen(false);
@@ -195,9 +196,12 @@ function EditableBudgetName() {
         />
       </InitialFocus>
     );
-  } else {
-    return (
+  }
+
+  return (
+    <>
       <Button
+        ref={triggerRef}
         type="bare"
         color={theme.buttonNormalBorder}
         style={{
@@ -212,16 +216,16 @@ function EditableBudgetName() {
           {budgetName || 'A budget has no name'}
         </Text>
         <SvgExpandArrow width={7} height={7} style={{ marginLeft: 5 }} />
-        {menuOpen && (
-          <Tooltip
-            position="bottom-left"
-            style={{ padding: 0 }}
-            onClose={() => setMenuOpen(false)}
-          >
-            <Menu onMenuSelect={onMenuSelect} items={items} />
-          </Tooltip>
-        )}
       </Button>
-    );
-  }
+
+      <Popover
+        triggerRef={triggerRef}
+        placement="bottom start"
+        isOpen={menuOpen}
+        onOpenChange={() => setMenuOpen(false)}
+      >
+        <Menu onMenuSelect={onMenuSelect} items={items} />
+      </Popover>
+    </>
+  );
 }
diff --git a/upcoming-release-notes/2593.md b/upcoming-release-notes/2593.md
new file mode 100644
index 0000000000000000000000000000000000000000..b94f89dfbf7db621be57b902bd55314e4633cce4
--- /dev/null
+++ b/upcoming-release-notes/2593.md
@@ -0,0 +1,6 @@
+---
+category: Maintenance
+authors: [MatissJanis]
+---
+
+Migrating native `Tooltip` component to react-aria Tooltip/Popover (vol.2)