diff --git a/packages/desktop-client/e2e/settings.test.js-snapshots/Settings-checks-the-page-visuals-1-chromium-linux.png b/packages/desktop-client/e2e/settings.test.js-snapshots/Settings-checks-the-page-visuals-1-chromium-linux.png
index 833c32d9a0e9e7e0494b80850a3116daf490a77a..e3724cb79825609ad01def74a2ce084ea9d6b3df 100644
Binary files a/packages/desktop-client/e2e/settings.test.js-snapshots/Settings-checks-the-page-visuals-1-chromium-linux.png and b/packages/desktop-client/e2e/settings.test.js-snapshots/Settings-checks-the-page-visuals-1-chromium-linux.png differ
diff --git a/packages/desktop-client/e2e/settings.test.js-snapshots/Settings-checks-the-page-visuals-2-chromium-linux.png b/packages/desktop-client/e2e/settings.test.js-snapshots/Settings-checks-the-page-visuals-2-chromium-linux.png
index 1f904d38122e542b09412daf30c8895a01a92808..e64c9a6a143ee7290b6dad5562de98ac72f7c3b8 100644
Binary files a/packages/desktop-client/e2e/settings.test.js-snapshots/Settings-checks-the-page-visuals-2-chromium-linux.png and b/packages/desktop-client/e2e/settings.test.js-snapshots/Settings-checks-the-page-visuals-2-chromium-linux.png differ
diff --git a/packages/desktop-client/e2e/settings.test.js-snapshots/Settings-checks-the-page-visuals-3-chromium-linux.png b/packages/desktop-client/e2e/settings.test.js-snapshots/Settings-checks-the-page-visuals-3-chromium-linux.png
index 0774a4ed58594e8dc55bf4f8167522f961ad8383..2986a14ddad72eedbe797c7d46ebf95cdb21d959 100644
Binary files a/packages/desktop-client/e2e/settings.test.js-snapshots/Settings-checks-the-page-visuals-3-chromium-linux.png and b/packages/desktop-client/e2e/settings.test.js-snapshots/Settings-checks-the-page-visuals-3-chromium-linux.png differ
diff --git a/packages/desktop-client/src/components/rules/RuleRow.tsx b/packages/desktop-client/src/components/rules/RuleRow.tsx
index 4b8a748a83c52713936f37b208e62224bf9e7873..913a6b045dd21cf04e4b22a7aed671e58168fd62 100644
--- a/packages/desktop-client/src/components/rules/RuleRow.tsx
+++ b/packages/desktop-client/src/components/rules/RuleRow.tsx
@@ -9,11 +9,11 @@ import { type RuleEntity } from 'loot-core/src/types/models';
 import { useSelectedDispatch } from '../../hooks/useSelected';
 import { SvgRightArrow2 } from '../../icons/v0';
 import { styles, theme } from '../../style';
-import { Button } from '../common/Button';
+import { Button } from '../common/Button2';
 import { Stack } from '../common/Stack';
 import { Text } from '../common/Text';
 import { View } from '../common/View';
-import { SelectCell, Row, Field, Cell, CellButton } from '../table';
+import { SelectCell, Row, Field, Cell } from '../table';
 
 import { ActionExpression } from './ActionExpression';
 import { ConditionExpression } from './ConditionExpression';
@@ -162,10 +162,7 @@ export const RuleRow = memo(
         </Field>
 
         <Cell name="edit" plain style={{ padding: '0 15px', paddingLeft: 5 }}>
-          {/* @ts-expect-error fix this later */}
-          <Button as={CellButton} onSelect={() => onEditRule(rule)}>
-            Edit
-          </Button>
+          <Button onPress={() => onEditRule(rule)}>Edit</Button>
         </Cell>
       </Row>
     );
diff --git a/packages/desktop-client/src/components/settings/Encryption.tsx b/packages/desktop-client/src/components/settings/Encryption.tsx
index ee76328f383e26882c9e9651ae18d4296efbdc75..1328af761c42151ebbe58de2ffe690a3599862f6 100644
--- a/packages/desktop-client/src/components/settings/Encryption.tsx
+++ b/packages/desktop-client/src/components/settings/Encryption.tsx
@@ -1,10 +1,12 @@
 // @ts-strict-ignore
 import React from 'react';
+import { useDispatch } from 'react-redux';
+
+import { pushModal } from 'loot-core/client/actions';
 
-import { useActions } from '../../hooks/useActions';
 import { useLocalPref } from '../../hooks/useLocalPref';
 import { theme } from '../../style';
-import { Button } from '../common/Button';
+import { Button } from '../common/Button2';
 import { Link } from '../common/Link';
 import { Text } from '../common/Text';
 import { useServerURL } from '../ServerContext';
@@ -12,19 +14,19 @@ import { useServerURL } from '../ServerContext';
 import { Setting } from './UI';
 
 export function EncryptionSettings() {
-  const { pushModal } = useActions();
+  const dispatch = useDispatch();
   const serverURL = useServerURL();
   const [encryptKeyId] = useLocalPref('encryptKeyId');
 
   const missingCryptoAPI = !(window.crypto && crypto.subtle);
 
   function onChangeKey() {
-    pushModal('create-encryption-key', { recreate: true });
+    dispatch(pushModal('create-encryption-key', { recreate: true }));
   }
 
   return encryptKeyId ? (
     <Setting
-      primaryAction={<Button onClick={onChangeKey}>Generate new key</Button>}
+      primaryAction={<Button onPress={onChangeKey}>Generate new key</Button>}
     >
       <Text>
         <Text style={{ color: theme.noticeTextLight, fontWeight: 600 }}>
@@ -43,7 +45,7 @@ export function EncryptionSettings() {
       </Text>
     </Setting>
   ) : missingCryptoAPI ? (
-    <Setting primaryAction={<Button disabled>Enable encryption…</Button>}>
+    <Setting primaryAction={<Button isDisabled>Enable encryption…</Button>}>
       <Text>
         <strong>End-to-end encryption</strong> is not available when making an
         unencrypted connection to a remote server. You’ll need to enable HTTPS
@@ -61,7 +63,7 @@ export function EncryptionSettings() {
   ) : serverURL ? (
     <Setting
       primaryAction={
-        <Button onClick={() => pushModal('create-encryption-key')}>
+        <Button onPress={() => dispatch(pushModal('create-encryption-key'))}>
           Enable encryption…
         </Button>
       }
@@ -82,7 +84,7 @@ export function EncryptionSettings() {
       </Text>
     </Setting>
   ) : (
-    <Setting primaryAction={<Button disabled>Enable encryption…</Button>}>
+    <Setting primaryAction={<Button isDisabled>Enable encryption…</Button>}>
       <Text>
         <strong>End-to-end encryption</strong> is not available when running
         without a server. Budget files are always kept unencrypted locally, and
diff --git a/packages/desktop-client/src/components/settings/Export.tsx b/packages/desktop-client/src/components/settings/Export.tsx
index b61f5d724a4fec696b8d1b597799315bacb12a61..7a9179becf0987cea4f14cf42498d91d6b7983d0 100644
--- a/packages/desktop-client/src/components/settings/Export.tsx
+++ b/packages/desktop-client/src/components/settings/Export.tsx
@@ -7,7 +7,7 @@ import { send } from 'loot-core/src/platform/client/fetch';
 import { useLocalPref } from '../../hooks/useLocalPref';
 import { theme } from '../../style';
 import { Block } from '../common/Block';
-import { ButtonWithLoading } from '../common/Button';
+import { ButtonWithLoading } from '../common/Button2';
 import { Text } from '../common/Text';
 
 import { Setting } from './UI';
@@ -43,7 +43,7 @@ export function ExportBudget() {
     <Setting
       primaryAction={
         <>
-          <ButtonWithLoading onClick={onExport} loading={isLoading}>
+          <ButtonWithLoading onPress={onExport} isLoading={isLoading}>
             Export data
           </ButtonWithLoading>
           {error && (
diff --git a/packages/desktop-client/src/components/settings/FixSplits.tsx b/packages/desktop-client/src/components/settings/FixSplits.tsx
index 8a8be2a7feb7f10c433ffe65e031ee2373badf00..17d712ad148b4ed64024c895f5111c4eb5291751 100644
--- a/packages/desktop-client/src/components/settings/FixSplits.tsx
+++ b/packages/desktop-client/src/components/settings/FixSplits.tsx
@@ -4,7 +4,7 @@ import { send } from 'loot-core/src/platform/client/fetch';
 import { type Handlers } from 'loot-core/src/types/handlers';
 
 import { theme } from '../../style';
-import { ButtonWithLoading } from '../common/Button';
+import { ButtonWithLoading } from '../common/Button2';
 import { Paragraph } from '../common/Paragraph';
 import { Text } from '../common/Text';
 import { View } from '../common/View';
@@ -74,7 +74,7 @@ export function FixSplits() {
             alignItems: 'center',
           }}
         >
-          <ButtonWithLoading loading={loading} onClick={onFix}>
+          <ButtonWithLoading isLoading={loading} onPress={onFix}>
             Repair split transactions
           </ButtonWithLoading>
           {results && renderResults(results)}
diff --git a/packages/desktop-client/src/components/settings/Format.tsx b/packages/desktop-client/src/components/settings/Format.tsx
index a64613b34f41126a14b8d9acd5ebf5f3728065a1..b4d4e7bdd3c0b55c3bc32715d256baeabc2fabe5 100644
--- a/packages/desktop-client/src/components/settings/Format.tsx
+++ b/packages/desktop-client/src/components/settings/Format.tsx
@@ -6,8 +6,8 @@ import { type LocalPrefs } from 'loot-core/src/types/prefs';
 
 import { useDateFormat } from '../../hooks/useDateFormat';
 import { useLocalPref } from '../../hooks/useLocalPref';
+import { type CSSProperties, theme } from '../../style';
 import { tokens } from '../../tokens';
-import { Button } from '../common/Button';
 import { Select } from '../common/Select';
 import { Text } from '../common/Text';
 import { View } from '../common/View';
@@ -65,6 +65,12 @@ export function FormatSettings() {
   const [hideFraction = false, setHideFractionPref] =
     useLocalPref('hideFraction');
 
+  const selectButtonStyle: CSSProperties = {
+    ':hover': {
+      backgroundColor: theme.buttonNormalBackgroundHover,
+    },
+  };
+
   return (
     <Setting
       primaryAction={
@@ -83,18 +89,16 @@ export function FormatSettings() {
           }}
         >
           <Column title="Numbers">
-            <Button bounce={false} style={{ padding: 0 }}>
-              <Select
-                bare
-                key={String(hideFraction)} // needed because label does not update
-                value={numberFormat}
-                onChange={setNumberFormatPref}
-                options={numberFormats.map(f => [
-                  f.value,
-                  hideFraction ? f.labelNoFraction : f.label,
-                ])}
-              />
-            </Button>
+            <Select
+              key={String(hideFraction)} // needed because label does not update
+              value={numberFormat}
+              onChange={format => setNumberFormatPref(format)}
+              options={numberFormats.map(f => [
+                f.value,
+                hideFraction ? f.labelNoFraction : f.label,
+              ])}
+              buttonStyle={selectButtonStyle}
+            />
 
             <Text style={{ display: 'flex' }}>
               <Checkbox
@@ -107,25 +111,21 @@ export function FormatSettings() {
           </Column>
 
           <Column title="Dates">
-            <Button bounce={false} style={{ padding: 0 }}>
-              <Select
-                bare
-                value={dateFormat}
-                onChange={setDateFormatPref}
-                options={dateFormats.map(f => [f.value, f.label])}
-              />
-            </Button>
+            <Select
+              value={dateFormat}
+              onChange={format => setDateFormatPref(format)}
+              options={dateFormats.map(f => [f.value, f.label])}
+              buttonStyle={selectButtonStyle}
+            />
           </Column>
 
           <Column title="First day of the week">
-            <Button bounce={false} style={{ padding: 0 }}>
-              <Select
-                bare
-                value={firstDayOfWeekIdx}
-                onChange={setFirstDayOfWeekIdxPref}
-                options={daysOfWeek.map(f => [f.value, f.label])}
-              />
-            </Button>
+            <Select
+              value={firstDayOfWeekIdx}
+              onChange={idx => setFirstDayOfWeekIdxPref(idx)}
+              options={daysOfWeek.map(f => [f.value, f.label])}
+              buttonStyle={selectButtonStyle}
+            />
           </Column>
         </View>
       }
diff --git a/packages/desktop-client/src/components/settings/Global.tsx b/packages/desktop-client/src/components/settings/Global.tsx
index da9fa01d744069d19a11695345fa26ab4bf17f35..242d76d40986174e3de50662ff67b1ed07bd049f 100644
--- a/packages/desktop-client/src/components/settings/Global.tsx
+++ b/packages/desktop-client/src/components/settings/Global.tsx
@@ -3,7 +3,7 @@ import React, { useState, useEffect, useRef } from 'react';
 import { useGlobalPref } from '../../hooks/useGlobalPref';
 import { theme } from '../../style';
 import { Information } from '../alerts';
-import { Button } from '../common/Button';
+import { Button } from '../common/Button2';
 import { Text } from '../common/Text';
 import { View } from '../common/View';
 
@@ -35,7 +35,7 @@ export function GlobalSettings() {
     <Setting
       primaryAction={
         <View style={{ flexDirection: 'row' }}>
-          <Button onClick={onChooseDocumentDir}>Change location</Button>
+          <Button onPress={onChooseDocumentDir}>Change location</Button>
           {documentDirChanged && (
             <Information>
               A restart is required for this change to take effect
diff --git a/packages/desktop-client/src/components/settings/Reset.tsx b/packages/desktop-client/src/components/settings/Reset.tsx
index 78d7f88a9dcf1ccfc2b4babea8c44464b2ea668f..9ceb5883a7c76d921a4569cd6a669e404996c479 100644
--- a/packages/desktop-client/src/components/settings/Reset.tsx
+++ b/packages/desktop-client/src/components/settings/Reset.tsx
@@ -4,7 +4,7 @@ import { send } from 'loot-core/src/platform/client/fetch';
 
 import { useActions } from '../../hooks/useActions';
 import { useLocalPref } from '../../hooks/useLocalPref';
-import { ButtonWithLoading } from '../common/Button';
+import { ButtonWithLoading } from '../common/Button2';
 import { Text } from '../common/Text';
 
 import { Setting } from './UI';
@@ -21,7 +21,7 @@ export function ResetCache() {
   return (
     <Setting
       primaryAction={
-        <ButtonWithLoading loading={resetting} onClick={onResetCache}>
+        <ButtonWithLoading isLoading={resetting} onPress={onResetCache}>
           Reset budget cache
         </ButtonWithLoading>
       }
@@ -54,9 +54,9 @@ export function ResetSync() {
     <Setting
       primaryAction={
         <ButtonWithLoading
-          loading={resetting}
-          disabled={!isEnabled}
-          onClick={onResetSync}
+          isLoading={resetting}
+          isDisabled={!isEnabled}
+          onPress={onResetSync}
         >
           Reset sync
         </ButtonWithLoading>
diff --git a/packages/desktop-client/src/components/settings/Themes.tsx b/packages/desktop-client/src/components/settings/Themes.tsx
index 494d7fc39eca1901db7b77df48c5c74d583068ee..44e713ae53f3b6c8e0decfcb2d50ba12cde55840 100644
--- a/packages/desktop-client/src/components/settings/Themes.tsx
+++ b/packages/desktop-client/src/components/settings/Themes.tsx
@@ -2,8 +2,7 @@ import React from 'react';
 
 import { type Theme } from 'loot-core/types/prefs';
 
-import { themeOptions, useTheme } from '../../style';
-import { Button } from '../common/Button';
+import { themeOptions, useTheme, theme as themeStyle } from '../../style';
 import { Select } from '../common/Select';
 import { Text } from '../common/Text';
 
@@ -15,14 +14,18 @@ export function ThemeSettings() {
   return (
     <Setting
       primaryAction={
-        <Button bounce={false} style={{ padding: 0 }}>
-          <Select<Theme>
-            bare
-            onChange={switchTheme}
-            value={theme}
-            options={themeOptions}
-          />
-        </Button>
+        <Select<Theme>
+          onChange={value => {
+            switchTheme(value);
+          }}
+          value={theme}
+          options={themeOptions}
+          buttonStyle={{
+            ':hover': {
+              backgroundColor: themeStyle.buttonNormalBackgroundHover,
+            },
+          }}
+        />
       }
     >
       <Text>
diff --git a/packages/desktop-client/src/components/settings/index.tsx b/packages/desktop-client/src/components/settings/index.tsx
index fe7c797110f97d63137116ebd00e09a5ce34992c..3da251d7680652120db2997917f8bd5d2e98669e 100644
--- a/packages/desktop-client/src/components/settings/index.tsx
+++ b/packages/desktop-client/src/components/settings/index.tsx
@@ -13,7 +13,7 @@ import { useSetThemeColor } from '../../hooks/useSetThemeColor';
 import { useResponsive } from '../../ResponsiveProvider';
 import { theme } from '../../style';
 import { tokens } from '../../tokens';
-import { Button } from '../common/Button';
+import { Button } from '../common/Button2';
 import { Input } from '../common/Input';
 import { Link } from '../common/Link';
 import { Text } from '../common/Text';
@@ -167,7 +167,7 @@ export function Settings() {
                 style={{ color: theme.buttonNormalDisabledText }}
               />
             </FormField>
-            <Button onClick={closeBudget}>Close Budget</Button>
+            <Button onPress={closeBudget}>Close Budget</Button>
           </View>
         )}
 
diff --git a/upcoming-release-notes/2913.md b/upcoming-release-notes/2913.md
new file mode 100644
index 0000000000000000000000000000000000000000..a1272ae7816d8996c9815f784fff40c64aba84ca
--- /dev/null
+++ b/upcoming-release-notes/2913.md
@@ -0,0 +1,6 @@
+---
+category: Maintenance
+authors: [joel-jeremy]
+---
+
+Use new react-aria-components based Button on settings and rules page.