diff --git a/packages/desktop-client/src/components/FatalError.js b/packages/desktop-client/src/components/FatalError.js
index b1067959db49afc084b3c8851bb0eadb83c52439..d111e8ffae5c88224c90b364d4c7ca9dae270405 100644
--- a/packages/desktop-client/src/components/FatalError.js
+++ b/packages/desktop-client/src/components/FatalError.js
@@ -179,20 +179,7 @@ function SharedArrayBufferOverride() {
       </Button>
     </>
   ) : (
-    <LinkButton
-      onClick={() => setExpanded(true)}
-      style={{
-        color: `inherit !important`,
-        marginLeft: 5,
-        border: 'none !important',
-        background: 'none !important',
-        padding: '0 !important',
-        textDecoration: 'underline !important',
-        boxShadow: 'none !important',
-        display: 'inline !important',
-        font: 'inherit !important',
-      }}
-    >
+    <LinkButton onClick={() => setExpanded(true)} style={{ marginLeft: 5 }}>
       Advanced options
     </LinkButton>
   );
diff --git a/packages/desktop-client/src/components/LoggedInUser.js b/packages/desktop-client/src/components/LoggedInUser.js
index 5692064a8fa2b9564bb284ada380abd3ac9a1bbf..a96d43fe5f5392c4c4d1de92638fdd09885634f3 100644
--- a/packages/desktop-client/src/components/LoggedInUser.js
+++ b/packages/desktop-client/src/components/LoggedInUser.js
@@ -87,7 +87,7 @@ function LoggedInUser({
 
   return (
     <View style={[{ flexDirection: 'row', alignItems: 'center' }, style]}>
-      <Button bare onClick={() => setMenuOpen(true)} style={{ color }}>
+      <Button type="bare" onClick={() => setMenuOpen(true)} style={{ color }}>
         {serverMessage()}
       </Button>
 
diff --git a/packages/desktop-client/src/components/ManageRules.js b/packages/desktop-client/src/components/ManageRules.js
index 30d21b5cfb7c7b478597aea912ff6bb33b485c96..b47684c2ee1d5f45daf048194c78b6ab48601d88 100644
--- a/packages/desktop-client/src/components/ManageRules.js
+++ b/packages/desktop-client/src/components/ManageRules.js
@@ -775,7 +775,7 @@ function ManageRulesContent({ isModal, payeeId, setLoading }) {
                 Delete {selectedInst.items.size} rules
               </Button>
             )}
-            <Button primary onClick={onCreateRule}>
+            <Button type="primary" onClick={onCreateRule}>
               Create new rule
             </Button>
           </Stack>
diff --git a/packages/desktop-client/src/components/NotesButton.tsx b/packages/desktop-client/src/components/NotesButton.tsx
index 5188adca177a59471384bc2e85c7be3c44995dcc..bd5d37fe68d57048afea6daa15f58a9028c16319 100644
--- a/packages/desktop-client/src/components/NotesButton.tsx
+++ b/packages/desktop-client/src/components/NotesButton.tsx
@@ -116,7 +116,7 @@ export default function NotesButton({
       onMouseLeave={handleMouseLeave}
     >
       <Button
-        bare
+        type="bare"
         className={!hasNotes && !tooltipOpen ? 'hover-visible' : ''}
         style={[
           { color: defaultColor },
diff --git a/packages/desktop-client/src/components/Notifications.tsx b/packages/desktop-client/src/components/Notifications.tsx
index 02baf1150a81c10d2b523173a9f1f3a77eef607d..aebc72c0ac43920482cd23eeb96493639699cec9 100644
--- a/packages/desktop-client/src/components/Notifications.tsx
+++ b/packages/desktop-client/src/components/Notifications.tsx
@@ -158,7 +158,7 @@ function Notification({
             : null}
           {button && (
             <ButtonWithLoading
-              bare
+              type="bare"
               loading={loading}
               onClick={async () => {
                 setLoading(true);
@@ -189,7 +189,7 @@ function Notification({
         </Stack>
         {sticky && (
           <Button
-            bare
+            type="bare"
             style={{ flexShrink: 0, color: 'currentColor' }}
             onClick={onRemove}
           >
diff --git a/packages/desktop-client/src/components/SidebarWithData.js b/packages/desktop-client/src/components/SidebarWithData.js
index d17b38cfe7abc447961b67554e58e8def6b8c613..5a3fb6ca43a665d10e3d9ea0021b88c14a0599b8 100644
--- a/packages/desktop-client/src/components/SidebarWithData.js
+++ b/packages/desktop-client/src/components/SidebarWithData.js
@@ -75,9 +75,9 @@ function EditableBudgetName({ prefs, savePrefs }) {
   } else {
     return (
       <Button
-        bare
+        type="bare"
+        color={colors.n9}
         style={{
-          color: colors.n9,
           fontSize: 16,
           fontWeight: 500,
           marginLeft: -5,
diff --git a/packages/desktop-client/src/components/ThemeSelector.tsx b/packages/desktop-client/src/components/ThemeSelector.tsx
index b745303d7aa1ab11bd99c701fefd1c971c8cecb9..cfc18c444ef7209d5194993b98054022a871be45 100644
--- a/packages/desktop-client/src/components/ThemeSelector.tsx
+++ b/packages/desktop-client/src/components/ThemeSelector.tsx
@@ -16,7 +16,7 @@ export function ThemeSelector() {
 
   return isNarrowWidth ? null : (
     <Button
-      bare
+      type="bare"
       onClick={() => {
         saveGlobalPrefs({
           theme: theme === 'dark' ? 'light' : 'dark',
diff --git a/packages/desktop-client/src/components/Titlebar.js b/packages/desktop-client/src/components/Titlebar.js
index 4502508521644a4214571bf78e6ff286ea52a3c3..ed4567b064095ba8035d31c25dac91c818dadd45 100644
--- a/packages/desktop-client/src/components/Titlebar.js
+++ b/packages/desktop-client/src/components/Titlebar.js
@@ -72,7 +72,7 @@ function UncategorizedButton() {
   return (
     count !== 0 && (
       <ButtonLink
-        bare
+        type="bare"
         to="/accounts/uncategorized"
         style={{ color: colors.r5 }}
       >
@@ -94,7 +94,7 @@ function PrivacyButton({ localPrefs, onTogglePrivacy }) {
   let privacyIconStyle = { width: 23, height: 23 };
 
   return (
-    <Button bare onClick={togglePrivacy}>
+    <Button type="bare" onClick={togglePrivacy}>
       {isPrivacyEnabled ? (
         <SvgEyeSlashed style={privacyIconStyle} />
       ) : (
@@ -143,7 +143,7 @@ export function SyncButton({ localPrefs, style, onSync }) {
 
   return (
     <Button
-      bare
+      type="bare"
       style={css(
         style,
         {
@@ -215,7 +215,7 @@ function BudgetTitlebar({ globalPrefs, saveGlobalPrefs, localPrefs }) {
       {reportBudgetEnabled && (
         <View style={{ marginLeft: -5 }}>
           <ButtonWithLoading
-            bare
+            type="bare"
             loading={loading}
             style={{
               alignSelf: 'flex-start',
@@ -247,7 +247,7 @@ function BudgetTitlebar({ globalPrefs, saveGlobalPrefs, localPrefs }) {
               </P>
               <P>
                 <ButtonWithLoading
-                  primary
+                  type="primary"
                   loading={loading}
                   onClick={onSwitchType}
                 >
@@ -315,7 +315,7 @@ function Titlebar({
     >
       {(floatingSidebar || sidebar.alwaysFloats) && (
         <Button
-          bare
+          type="bare"
           style={{ marginRight: 8 }}
           onPointerEnter={e => {
             if (e.pointerType === 'mouse') {
@@ -345,7 +345,7 @@ function Titlebar({
           path="/accounts"
           element={
             location.state?.goBack ? (
-              <Button onClick={() => navigate(-1)} bare>
+              <Button type="bare" onClick={() => navigate(-1)}>
                 <ArrowLeft
                   width={10}
                   height={10}
diff --git a/packages/desktop-client/src/components/UpdateNotification.js b/packages/desktop-client/src/components/UpdateNotification.js
index b66653bc92e14027f3e88bc7e52592d771fbba30..f7762bbad962997583d4adf20c039c7c6dc71e37 100644
--- a/packages/desktop-client/src/components/UpdateNotification.js
+++ b/packages/desktop-client/src/components/UpdateNotification.js
@@ -68,7 +68,7 @@ function UpdateNotification({
               </LinkButton>
               )
               <Button
-                bare
+                type="bare"
                 style={{ display: 'inline', padding: '1px 7px 2px 7px' }}
                 onClick={() => closeNotification(setAppState)}
               >
diff --git a/packages/desktop-client/src/components/accounts/Account.js b/packages/desktop-client/src/components/accounts/Account.js
index a38f79ae4f941340eb7ce66add9cf824b2b66a25..d9526f8f468509fb149ff0c159fbd23d1e802998 100644
--- a/packages/desktop-client/src/components/accounts/Account.js
+++ b/packages/desktop-client/src/components/accounts/Account.js
@@ -62,7 +62,7 @@ function EmptyMessage({ onAdd }) {
           manage it locally yourself.
         </Text>
 
-        <Button primary style={{ marginTop: 20 }} onClick={onAdd}>
+        <Button type="primary" style={{ marginTop: 20 }} onClick={onAdd}>
           Add account
         </Button>
 
diff --git a/packages/desktop-client/src/components/accounts/AccountSyncCheck.js b/packages/desktop-client/src/components/accounts/AccountSyncCheck.js
index 412c835a8153f500063a51225404b58e5c6da9a9..df6dcc7e0f9184f5b697fe1fe2ef48a710d6b34d 100644
--- a/packages/desktop-client/src/components/accounts/AccountSyncCheck.js
+++ b/packages/desktop-client/src/components/accounts/AccountSyncCheck.js
@@ -83,7 +83,7 @@ function AccountSyncCheck({
   return (
     <View>
       <Button
-        bare
+        type="bare"
         style={{
           flexDirection: 'row',
           alignItems: 'center',
@@ -116,7 +116,11 @@ function AccountSyncCheck({
             {showAuth ? (
               <>
                 <Button onClick={unlink}>Unlink</Button>
-                <Button primary onClick={reauth} style={{ marginLeft: 5 }}>
+                <Button
+                  type="primary"
+                  onClick={reauth}
+                  style={{ marginLeft: 5 }}
+                >
                   Reauthorize
                 </Button>
               </>
diff --git a/packages/desktop-client/src/components/accounts/Balance.js b/packages/desktop-client/src/components/accounts/Balance.js
index 5bbdb0126680993aecaa5de262126893aa0da442..aee068dfd92b45b7d74c669eff6c51765404baf9 100644
--- a/packages/desktop-client/src/components/accounts/Balance.js
+++ b/packages/desktop-client/src/components/accounts/Balance.js
@@ -121,7 +121,7 @@ export function Balances({
     >
       <Button
         data-testid="account-balance"
-        bare
+        type="bare"
         onClick={onToggleExtraBalances}
         style={{
           '& svg': {
diff --git a/packages/desktop-client/src/components/accounts/Header.js b/packages/desktop-client/src/components/accounts/Header.js
index 7b1cd9116fedf151c794d0883c2aa249f1d9b0d0..0a236c3b32394f6883752b86dc8edc1e3a9a5e7c 100644
--- a/packages/desktop-client/src/components/accounts/Header.js
+++ b/packages/desktop-client/src/components/accounts/Header.js
@@ -165,7 +165,7 @@ export function AccountHeader({
 
                 {account && <NotesButton id={`account-${account.id}`} />}
                 <Button
-                  bare
+                  type="bare"
                   className="hover-visible"
                   onClick={() => onExposeName(true)}
                 >
@@ -205,7 +205,7 @@ export function AccountHeader({
           style={{ marginTop: 12 }}
         >
           {((account && !account.closed) || canSync) && (
-            <Button bare onClick={canSync ? onSync : onImport}>
+            <Button type="bare" onClick={canSync ? onSync : onImport}>
               {canSync ? (
                 <>
                   <AnimatedRefresh
@@ -232,7 +232,7 @@ export function AccountHeader({
             </Button>
           )}
           {!showEmptyMessage && (
-            <Button bare onClick={onAddTransaction}>
+            <Button type="bare" onClick={onAddTransaction}>
               <Add width={10} height={10} style={{ marginRight: 3 }} /> Add New
             </Button>
           )}
@@ -255,7 +255,7 @@ export function AccountHeader({
             rightContent={
               search && (
                 <Button
-                  bare
+                  type="bare"
                   style={{ padding: 8 }}
                   onClick={() => onSearch('')}
                   title="Clear search term"
@@ -306,7 +306,7 @@ export function AccountHeader({
             />
           )}
           <Button
-            bare
+            type="bare"
             disabled={search !== '' || filters.length > 0}
             style={{ padding: 6 }}
             onClick={onToggleSplits}
diff --git a/packages/desktop-client/src/components/accounts/MobileAccountDetails.js b/packages/desktop-client/src/components/accounts/MobileAccountDetails.js
index f254ba6c8e67757e424da389490b54bd6f5ac97d..0cf4741820606510afb0e69d75c9d5499c4c6a9c 100644
--- a/packages/desktop-client/src/components/accounts/MobileAccountDetails.js
+++ b/packages/desktop-client/src/components/accounts/MobileAccountDetails.js
@@ -132,7 +132,7 @@ export default function AccountDetails({
           */}
           <Link to="transaction/new" style={{ visibility: 'hidden' }}>
             <Button
-              bare
+              type="bare"
               style={{ justifyContent: 'center', width: LEFT_RIGHT_FLEX_WIDTH }}
             >
               <Add width={20} height={20} />
diff --git a/packages/desktop-client/src/components/accounts/MobileAccounts.js b/packages/desktop-client/src/components/accounts/MobileAccounts.js
index 32f8979763e872ae9c4f856e091285768c15639e..cd03c6a137673b8b4854d4e52b6f0132fb2f6928 100644
--- a/packages/desktop-client/src/components/accounts/MobileAccounts.js
+++ b/packages/desktop-client/src/components/accounts/MobileAccounts.js
@@ -123,7 +123,7 @@ function EmptyMessage({ onAdd }) {
       </Text>
 
       <Button
-        primary
+        type="primary"
         style={{ marginTop: 20, alignSelf: 'center' }}
         onClick={() =>
           alert(
diff --git a/packages/desktop-client/src/components/accounts/Reconcile.js b/packages/desktop-client/src/components/accounts/Reconcile.js
index b542d9520ec7e677af1639498deb3be9da04e399..191109f669ddf91ca1af116f64d84f3850ed7f13 100644
--- a/packages/desktop-client/src/components/accounts/Reconcile.js
+++ b/packages/desktop-client/src/components/accounts/Reconcile.js
@@ -73,7 +73,7 @@ export function ReconcilingMessage({
           </View>
         )}
         <View style={{ marginLeft: 15 }}>
-          <Button primary onClick={onDone}>
+          <Button type="primary" onClick={onDone}>
             Done Reconciling
           </Button>
         </View>
@@ -120,7 +120,7 @@ export function ReconcileTooltip({ account, onReconcile, onClose }) {
               />
             </InitialFocus>
           )}
-          <Button primary>Reconcile</Button>
+          <Button type="primary">Reconcile</Button>
         </form>
       </View>
     </Tooltip>
diff --git a/packages/desktop-client/src/components/autocomplete/Autocomplete.tsx b/packages/desktop-client/src/components/autocomplete/Autocomplete.tsx
index 85edbc80f15eebb01a29c7efa0df0909ee35a4a8..32845461c3910f296ffa53cf8de9146eecb034ae 100644
--- a/packages/desktop-client/src/components/autocomplete/Autocomplete.tsx
+++ b/packages/desktop-client/src/components/autocomplete/Autocomplete.tsx
@@ -510,7 +510,7 @@ function MultiItem({ name, onRemove }) {
       }}
     >
       {name}
-      <Button type="button" bare style={{ marginLeft: 1 }} onClick={onRemove}>
+      <Button type="bare" style={{ marginLeft: 1 }} onClick={onRemove}>
         <Remove style={{ width: 8, height: 8 }} />
       </Button>
     </View>
@@ -629,34 +629,6 @@ function MultiAutocomplete({
   );
 }
 
-export function AutocompleteFooterButton({
-  title,
-  style,
-  hoveredStyle,
-  onClick,
-}) {
-  return (
-    <Button
-      style={[
-        {
-          fontSize: 12,
-          color: colors.n10,
-          backgroundColor: 'transparent',
-          borderColor: colors.n5,
-        },
-        style,
-      ]}
-      hoveredStyle={[
-        { backgroundColor: 'rgba(200, 200, 200, .25)' },
-        hoveredStyle,
-      ]}
-      onClick={onClick}
-    >
-      {title}
-    </Button>
-  );
-}
-
 type AutocompleteFooterProps = {
   show?: boolean;
   embedded: boolean;
diff --git a/packages/desktop-client/src/components/autocomplete/PayeeAutocomplete.js b/packages/desktop-client/src/components/autocomplete/PayeeAutocomplete.js
index f950b82557b31979e82de85112f261f875d43787..f5d3700b206a2a948390b417a39a13b99b8d52dd 100644
--- a/packages/desktop-client/src/components/autocomplete/PayeeAutocomplete.js
+++ b/packages/desktop-client/src/components/autocomplete/PayeeAutocomplete.js
@@ -8,12 +8,11 @@ import { getActivePayees } from 'loot-core/src/client/reducers/queries';
 
 import Add from '../../icons/v1/Add';
 import { colors } from '../../style';
-import { View } from '../common';
+import { View, Button } from '../common';
 
 import Autocomplete, {
   defaultFilterSuggestion,
   AutocompleteFooter,
-  AutocompleteFooterButton,
 } from './Autocomplete';
 
 function getPayeeSuggestions(payees, focusTransferPayees, accounts) {
@@ -327,33 +326,21 @@ export default function PayeeAutocomplete({
           footer={
             <AutocompleteFooter embedded={embedded}>
               {showMakeTransfer && (
-                <AutocompleteFooterButton
-                  title="Make Transfer"
-                  style={[
-                    showManagePayees && { marginBottom: 5 },
-                    focusTransferPayees && {
-                      backgroundColor: colors.y8,
-                      color: colors.g2,
-                      borderColor: colors.y8,
-                    },
-                  ]}
-                  hoveredStyle={
-                    focusTransferPayees && {
-                      backgroundColor: colors.y8,
-                      colors: colors.y2,
-                    }
-                  }
+                <Button
+                  type={focusTransferPayees ? 'menuSelected' : 'menu'}
+                  style={showManagePayees && { marginBottom: 5 }}
                   onClick={() => {
                     onUpdate?.(null);
                     setFocusTransferPayees(!focusTransferPayees);
                   }}
-                />
+                >
+                  Make Transfer
+                </Button>
               )}
               {showManagePayees && (
-                <AutocompleteFooterButton
-                  title="Manage Payees"
-                  onClick={() => onManagePayees()}
-                />
+                <Button type="menu" onClick={() => onManagePayees()}>
+                  Manage Payees
+                </Button>
               )}
             </AutocompleteFooter>
           }
diff --git a/packages/desktop-client/src/components/budget/MobileBudgetTable.js b/packages/desktop-client/src/components/budget/MobileBudgetTable.js
index cdca7c4a321fc17ab574f2bb0831987eb6e9e341..acc5c077d260d726e88f1a581a951a957b79bf9d 100644
--- a/packages/desktop-client/src/components/budget/MobileBudgetTable.js
+++ b/packages/desktop-client/src/components/budget/MobileBudgetTable.js
@@ -38,7 +38,7 @@ function ToBudget({ toBudget, onClick }) {
   let amount = useSheetValue(toBudget);
   return (
     <Button
-      bare
+      type="bare"
       style={{ flexDirection: 'column', alignItems: 'flex-start' }}
       onClick={onClick}
     >
@@ -1039,7 +1039,7 @@ function UnconnectedBudgetHeader({
     >
       {!editMode && (
         <Button
-          bare
+          type="bare"
           // hitSlop={{ top: 5, bottom: 5, left: 0, right: 30 }}
 
           onClick={prevEnabled && onPrevMonth}
@@ -1072,7 +1072,7 @@ function UnconnectedBudgetHeader({
       </Text>
       {editMode ? (
         <Button
-          bare
+          type="bare"
           onClick={onDone}
           style={[
             buttonStyle,
@@ -1089,7 +1089,7 @@ function UnconnectedBudgetHeader({
       ) : (
         <>
           <Button
-            bare
+            type="bare"
             onClick={nextEnabled && onNextMonth}
             // hitSlop={{ top: 5, bottom: 5, left: 30, right: 5 }}
             style={[buttonStyle, { opacity: nextEnabled ? 1 : 0.6 }]}
@@ -1116,7 +1116,7 @@ function UnconnectedBudgetHeader({
             onSync={sync}
           />
           {/* <Button
-            bare
+            type="bare"
             onClick={() => setMenuOpen(true)}
             style={{
               position: 'absolute',
diff --git a/packages/desktop-client/src/components/budget/misc.js b/packages/desktop-client/src/components/budget/misc.js
index 2360e2204ef624537603f04a91f624383ee8e1bd..d38c44f18d8f4f9092f1babfea425a583bcbf57b 100644
--- a/packages/desktop-client/src/components/budget/misc.js
+++ b/packages/desktop-client/src/components/budget/misc.js
@@ -368,7 +368,7 @@ function SidebarCategory({
       </div>
       <View style={{ flexShrink: 0, marginLeft: 5 }}>
         <Button
-          bare
+          type="bare"
           onClick={e => {
             e.stopPropagation();
             setMenuOpen(true);
@@ -537,7 +537,7 @@ function SidebarGroup({
         <>
           <View style={{ marginLeft: 5, flexShrink: 0 }}>
             <Button
-              bare
+              type="bare"
               onClick={e => {
                 e.stopPropagation();
                 setMenuOpen(true);
@@ -701,7 +701,7 @@ const BudgetTotals = memo(function BudgetTotals({
       >
         <View style={{ flexGrow: '1' }}>Category</View>
         <Button
-          bare
+          type="bare"
           onClick={() => {
             setMenuOpen(true);
           }}
diff --git a/packages/desktop-client/src/components/budget/report/BudgetSummary.tsx b/packages/desktop-client/src/components/budget/report/BudgetSummary.tsx
index 8c7f140e086bed8e99ac269b6f8ff079b33702ad..a56afd3e73e6bdf8ab80a852b764e0a7c1346d3b 100644
--- a/packages/desktop-client/src/components/budget/report/BudgetSummary.tsx
+++ b/packages/desktop-client/src/components/budget/report/BudgetSummary.tsx
@@ -352,8 +352,8 @@ export function BudgetSummary({ month }: BudgetSummaryProps) {
             }}
           >
             <Button
+              type="bare"
               className="hover-visible"
-              bare
               onClick={onToggleSummaryCollapse}
             >
               <ExpandOrCollapseIcon
@@ -399,7 +399,7 @@ export function BudgetSummary({ month }: BudgetSummaryProps) {
               />
             </View>
             <View style={{ userSelect: 'none' }}>
-              <Button bare onClick={onMenuOpen}>
+              <Button type="bare" onClick={onMenuOpen}>
                 <DotsHorizontalTriple
                   width={15}
                   height={15}
diff --git a/packages/desktop-client/src/components/budget/rollover/BudgetSummary.tsx b/packages/desktop-client/src/components/budget/rollover/BudgetSummary.tsx
index ce0e1ccc8c477fe6cc940cbd6a70bcdc0db1dbca..97782af2279d56c5c19808296ec3b308a829ecbd 100644
--- a/packages/desktop-client/src/components/budget/rollover/BudgetSummary.tsx
+++ b/packages/desktop-client/src/components/budget/rollover/BudgetSummary.tsx
@@ -325,8 +325,8 @@ export function BudgetSummary({
             }}
           >
             <Button
+              type="bare"
               className="hover-visible"
-              bare
               onClick={onToggleSummaryCollapse}
             >
               <ExpandOrCollapseIcon
@@ -372,7 +372,7 @@ export function BudgetSummary({
               />
             </View>
             <View style={{ userSelect: 'none', marginLeft: 2 }}>
-              <Button bare onClick={onMenuOpen}>
+              <Button type="bare" onClick={onMenuOpen}>
                 <DotsHorizontalTriple
                   width={15}
                   height={15}
diff --git a/packages/desktop-client/src/components/budget/rollover/HoldTooltip.tsx b/packages/desktop-client/src/components/budget/rollover/HoldTooltip.tsx
index fe0bf61dfea65732ba6e6c27b54c605ecb88dffd..68573a38f218bdc7df55ca9d58bc788dc3717356 100644
--- a/packages/desktop-client/src/components/budget/rollover/HoldTooltip.tsx
+++ b/packages/desktop-client/src/components/budget/rollover/HoldTooltip.tsx
@@ -68,7 +68,7 @@ export default function HoldTooltip({ onSubmit, onClose }: HoldTooltipProps) {
         }}
       >
         <Button
-          primary
+          type="primary"
           style={{
             fontSize: 12,
             paddingTop: 3,
diff --git a/packages/desktop-client/src/components/budget/rollover/TransferTooltip.tsx b/packages/desktop-client/src/components/budget/rollover/TransferTooltip.tsx
index e4829c9e8bf5b615dbcd26b843dbb10bccd000ab..f5c001457132945a6312eba3138e4af091cb18a3 100644
--- a/packages/desktop-client/src/components/budget/rollover/TransferTooltip.tsx
+++ b/packages/desktop-client/src/components/budget/rollover/TransferTooltip.tsx
@@ -105,7 +105,7 @@ export default function TransferTooltip({
         }}
       >
         <Button
-          primary
+          type="primary"
           style={{
             fontSize: 12,
             paddingTop: 3,
diff --git a/packages/desktop-client/src/components/budget/rollover/rollover-components.tsx b/packages/desktop-client/src/components/budget/rollover/rollover-components.tsx
index 621cce40169255514cc5c03b6c820db5e80f1b50..6b33a8a224e38da51a525e293f7db5d2543c5c1a 100644
--- a/packages/desktop-client/src/components/budget/rollover/rollover-components.tsx
+++ b/packages/desktop-client/src/components/budget/rollover/rollover-components.tsx
@@ -87,7 +87,7 @@ function CoverTooltip({ tooltipProps, onSubmit, onClose }: CoverTooltipProps) {
         }}
       >
         <Button
-          primary
+          type="primary"
           style={{
             fontSize: 12,
             paddingTop: 3,
diff --git a/packages/desktop-client/src/components/common.tsx b/packages/desktop-client/src/components/common.tsx
index a96458ec70c52b289fbb5c7bd3fd4f680b140199..0c8e33dd06e4de357c0c0ef49dae3504a0d0f6bc 100644
--- a/packages/desktop-client/src/components/common.tsx
+++ b/packages/desktop-client/src/components/common.tsx
@@ -36,6 +36,7 @@ export { default as Stack } from './Stack';
 export { default as Text } from './common/Text';
 export { default as TextOneLine } from './common/TextOneLine';
 export { default as View } from './common/View';
+export { default as LinkButton } from './common/LinkButton';
 
 type UseStableCallbackArg = (...args: unknown[]) => unknown;
 
@@ -51,39 +52,6 @@ export const useStableCallback = (callback: UseStableCallbackArg) => {
   return memoCallback;
 };
 
-type LinkProps = ComponentProps<typeof Button>;
-
-export function LinkButton({ style, children, ...nativeProps }: LinkProps) {
-  return (
-    <Button
-      style={[
-        {
-          textDecoration: 'none',
-          color: styles.textColor,
-          backgroundColor: 'transparent',
-          display: 'inline',
-          border: 0,
-          cursor: 'pointer',
-          padding: 0,
-          font: 'inherit',
-          ':hover': {
-            textDecoration: 'underline',
-            boxShadow: 'none',
-          },
-          ':focus': {
-            boxShadow: 'none',
-          },
-        },
-        styles.smallText,
-        style,
-      ]}
-      {...nativeProps}
-    >
-      {children}
-    </Button>
-  );
-}
-
 type AnchorLinkProps = {
   to: string;
   style?: CSSProperties;
diff --git a/packages/desktop-client/src/components/common/Button.tsx b/packages/desktop-client/src/components/common/Button.tsx
index 3655496390f07d7e0676ad95e585fc153f0e46a2..02d2917ec5349132b44875700808d334999ede89 100644
--- a/packages/desktop-client/src/components/common/Button.tsx
+++ b/packages/desktop-client/src/components/common/Button.tsx
@@ -3,17 +3,18 @@ import React, { forwardRef } from 'react';
 import { css, type CSSProperties } from 'glamor';
 
 import AnimatedLoading from '../../icons/AnimatedLoading';
-import { styles, colors } from '../../style';
+import { styles, theme } from '../../style';
 import { type HTMLPropsWithStyle } from '../../types/utils';
 
 import View from './View';
 
 type ButtonProps = HTMLPropsWithStyle<HTMLButtonElement> & {
   pressed?: boolean;
-  primary?: boolean;
   hover?: boolean;
-  bare?: boolean;
+  type?: ButtonType;
+  isSubmit?: boolean;
   disabled?: boolean;
+  color?: string;
   hoveredStyle?: CSSProperties;
   activeStyle?: CSSProperties;
   textStyle?: CSSProperties;
@@ -21,14 +22,64 @@ type ButtonProps = HTMLPropsWithStyle<HTMLButtonElement> & {
   as?: 'button';
 };
 
+type ButtonType = 'normal' | 'primary' | 'bare';
+
+const backgroundColor = {
+  normal: theme.buttonNormalBackground,
+  normalDisabled: theme.buttonNormalDisabledBackground,
+  primary: theme.buttonPrimaryBackground,
+  primaryDisabled: theme.buttonPrimaryDisabledBackground,
+  bare: theme.buttonBareBackground,
+  bareDisabled: theme.buttonBareDisabledBackground,
+  menu: theme.buttonMenuBackground,
+  menuSelected: theme.buttonMenuSelectedBackground,
+};
+
+const backgroundColorHover = {
+  normal: theme.buttonNormalBackgroundHover,
+  primary: theme.buttonPrimaryBackgroundHover,
+  bare: theme.buttonBareBackgroundHover,
+  menu: theme.buttonMenuBackgroundHover,
+  menuSelected: theme.buttonMenuSelectedBackgroundHover,
+};
+
+const borderColor = {
+  normal: theme.buttonNormalBorder,
+  normalDisabled: theme.buttonNormalDisabledBorder,
+  primary: theme.buttonPrimaryBorder,
+  primaryDisabled: theme.buttonPrimaryDisabledBorder,
+  menu: theme.buttonMenuBorder,
+  menuSelected: theme.buttonMenuSelectedBorder,
+};
+
+const textColor = {
+  normal: theme.buttonNormalText,
+  normalDisabled: theme.buttonNormalDisabledText,
+  primary: theme.buttonPrimaryText,
+  primaryDisabled: theme.buttonPrimaryDisabledText,
+  bare: theme.buttonBareText,
+  bareDisabled: theme.buttonBareDisabledText,
+  menu: theme.buttonMenuText,
+  menuSelected: theme.buttonMenuSelectedText,
+};
+
+const textColorHover = {
+  normal: theme.buttonNormalTextHover,
+  primary: theme.buttonPrimaryTextHover,
+  bare: theme.buttonBareTextHover,
+  menu: theme.buttonMenuTextHover,
+  menuSelected: theme.buttonMenuSelectedTextHover,
+};
+
 const Button = forwardRef<HTMLButtonElement, ButtonProps>(
   (
     {
       children,
       pressed,
-      primary,
       hover,
-      bare,
+      type = 'normal',
+      isSubmit = type === 'primary',
+      color,
       style,
       disabled,
       hoveredStyle,
@@ -39,22 +90,26 @@ const Button = forwardRef<HTMLButtonElement, ButtonProps>(
     },
     ref,
   ) => {
+    let typeWithDisabled = disabled ? type + 'Disabled' : type;
+
     hoveredStyle = [
-      bare
-        ? { backgroundColor: 'rgba(100, 100, 100, .15)' }
-        : { ...styles.shadow },
+      type !== 'bare' && styles.shadow,
       hoveredStyle,
+      {
+        backgroundColor: backgroundColorHover[type],
+        color: color || textColorHover[type],
+      },
     ];
     activeStyle = [
-      bare
-        ? { backgroundColor: 'rgba(100, 100, 100, .25)' }
+      type === 'bare'
+        ? { backgroundColor: theme.buttonBareBackgroundActive }
         : {
             transform: bounce && 'translateY(1px)',
             boxShadow:
-              !bare &&
-              (primary
-                ? '0 1px 4px 0 rgba(0,0,0,0.3)'
-                : '0 1px 4px 0 rgba(0,0,0,0.2)'),
+              '0 1px 4px 0 ' +
+              (type === 'primary'
+                ? theme.buttonPrimaryShadow
+                : theme.buttonNormalShadow),
             transition: 'none',
           },
       activeStyle,
@@ -66,23 +121,17 @@ const Button = forwardRef<HTMLButtonElement, ButtonProps>(
         alignItems: 'center',
         justifyContent: 'center',
         flexShrink: 0,
-        padding: bare ? '5px' : '5px 10px',
+        padding: type === 'bare' ? '5px' : '5px 10px',
         margin: 0,
         overflow: 'hidden',
         display: 'flex',
         borderRadius: 4,
-        backgroundColor: bare
-          ? 'transparent'
-          : primary
-          ? disabled
-            ? colors.n7
-            : colors.p5
-          : 'white',
-        border: bare
-          ? 'none'
-          : '1px solid ' +
-            (primary ? (disabled ? colors.n7 : colors.p5) : colors.n9),
-        color: primary ? 'white' : disabled ? colors.n6 : colors.n1,
+        backgroundColor: backgroundColor[typeWithDisabled],
+        border:
+          type === 'bare'
+            ? 'none'
+            : '1px solid ' + borderColor[typeWithDisabled],
+        color: color || textColor[typeWithDisabled],
         transition: 'box-shadow .25s',
         WebkitAppRegion: 'no-drag',
         ...styles.smallText,
@@ -100,7 +149,7 @@ const Button = forwardRef<HTMLButtonElement, ButtonProps>(
         {...(typeof as === 'string'
           ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
             (css(buttonStyle) as any)
-          : { style: buttonStyle })}
+          : { style: buttonStyle, type: isSubmit ? 'submit' : 'button' })}
         disabled={disabled}
         {...nativeProps}
       >
diff --git a/packages/desktop-client/src/components/common/LinkButton.tsx b/packages/desktop-client/src/components/common/LinkButton.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..8c64d45214e5aeb32721613932ecc832cee6701e
--- /dev/null
+++ b/packages/desktop-client/src/components/common/LinkButton.tsx
@@ -0,0 +1,43 @@
+import React, { type HTMLAttributes } from 'react';
+
+import { css } from 'glamor';
+
+import { styles, theme } from '../../style';
+
+type LinkProps = HTMLAttributes<HTMLButtonElement>;
+
+export default function LinkButton({
+  style,
+  children,
+  ...nativeProps
+}: LinkProps) {
+  return (
+    <button
+      type="button"
+      {...css([
+        {
+          textDecoration: 'none',
+          color: theme.pageTextLink,
+          backgroundColor: 'transparent',
+          display: 'inline',
+          border: 0,
+          cursor: 'pointer',
+          padding: 0,
+          font: 'inherit',
+          ':hover': {
+            textDecoration: 'underline',
+            boxShadow: 'none',
+          },
+          ':focus': {
+            boxShadow: 'none',
+          },
+        },
+        styles.smallText,
+        style,
+      ])}
+      {...nativeProps}
+    >
+      {children}
+    </button>
+  );
+}
diff --git a/packages/desktop-client/src/components/common/MenuButton.tsx b/packages/desktop-client/src/components/common/MenuButton.tsx
index 1e6c24650bd0d48809392bfec70d2bf862b143d7..66d4b58ec23f0aa90916a1c757fa59bedcf7b573 100644
--- a/packages/desktop-client/src/components/common/MenuButton.tsx
+++ b/packages/desktop-client/src/components/common/MenuButton.tsx
@@ -6,7 +6,7 @@ import Button from './Button';
 
 export default function MenuButton({ onClick }) {
   return (
-    <Button bare onClick={onClick} aria-label="Menu">
+    <Button type="bare" onClick={onClick} aria-label="Menu">
       <DotsHorizontalTriple
         width={15}
         height={15}
diff --git a/packages/desktop-client/src/components/common/Modal.tsx b/packages/desktop-client/src/components/common/Modal.tsx
index ecbee88e04a537351a363c9f9f2954fa0e40fa26..863c4208e9bbd258d4b8917dd3ffaba85c2ca498 100644
--- a/packages/desktop-client/src/components/common/Modal.tsx
+++ b/packages/desktop-client/src/components/common/Modal.tsx
@@ -188,7 +188,7 @@ const Modal = ({
               >
                 {showClose && (
                   <Button
-                    bare
+                    type="bare"
                     onClick={onClose}
                     style={{ padding: '10px 10px' }}
                     aria-label="Close"
diff --git a/packages/desktop-client/src/components/filters/FiltersMenu.js b/packages/desktop-client/src/components/filters/FiltersMenu.js
index 044f8361408fa8389633163e5bf3ba77bf88569e..987752f157786bf5ad6176d50062c7350ebcf28d 100644
--- a/packages/desktop-client/src/components/filters/FiltersMenu.js
+++ b/packages/desktop-client/src/components/filters/FiltersMenu.js
@@ -88,7 +88,7 @@ function subfieldToOptions(field, subfield) {
 function OpButton({ op, selected, style, onClick }) {
   return (
     <Button
-      bare
+      type="bare"
       style={[
         { backgroundColor: colors.n10, marginBottom: 5 },
         style,
@@ -300,7 +300,7 @@ function ConfigureField({
           >
             <View style={{ flex: 1 }} />
             <Button
-              primary
+              type="primary"
               onClick={e => {
                 e.preventDefault();
                 onApply({
@@ -403,7 +403,7 @@ export function FilterButton({ onApply }) {
 
   return (
     <View>
-      <Button bare onClick={() => dispatch({ type: 'select-field' })}>
+      <Button type="bare" onClick={() => dispatch({ type: 'select-field' })}>
         <SettingsSliderAlternate
           style={{ width: 16, height: 16, marginRight: 5 }}
         />{' '}
@@ -499,7 +499,7 @@ function FilterExpression({
       ]}
     >
       <Button
-        bare
+        type="bare"
         disabled={customName != null}
         onClick={() => setEditing(true)}
         style={{ marginRight: -7 }}
@@ -523,7 +523,7 @@ function FilterExpression({
           )}
         </div>
       </Button>
-      <Button bare onClick={onDelete}>
+      <Button type="bare" onClick={onDelete}>
         <DeleteIcon
           style={{
             width: 8,
diff --git a/packages/desktop-client/src/components/filters/SavedFilters.js b/packages/desktop-client/src/components/filters/SavedFilters.js
index eff68869058220053ddb95e46bdc203abb5ec170..eabf7657582aa7e7c717faca9a2d712b785b73c0 100644
--- a/packages/desktop-client/src/components/filters/SavedFilters.js
+++ b/packages/desktop-client/src/components/filters/SavedFilters.js
@@ -200,8 +200,7 @@ function SavedFilterMenuButton({
                 />
               </FormField>
               <Button
-                primary
-                type="submit"
+                type="primary"
                 style={{ marginTop: 18 }}
                 onClick={e => {
                   e.preventDefault();
@@ -226,7 +225,7 @@ function SavedFilterMenuButton({
     <View>
       {filters.length > 0 && (
         <Button
-          bare
+          type="bare"
           style={{ marginTop: 10 }}
           onClick={() => {
             setMenuOpen(true);
diff --git a/packages/desktop-client/src/components/manager/BudgetList.js b/packages/desktop-client/src/components/manager/BudgetList.js
index 9d76800e2cf8253d5c629e56f48a4d3b84d183be..b5300577a4921b5c7b398cd468725904b6dd2eeb 100644
--- a/packages/desktop-client/src/components/manager/BudgetList.js
+++ b/packages/desktop-client/src/components/manager/BudgetList.js
@@ -57,7 +57,7 @@ function DetailButton({ state, onDelete }) {
   return (
     <View>
       <Button
-        bare
+        type="bare"
         onClick={e => {
           e.stopPropagation();
           setMenuOpen(true);
@@ -228,7 +228,11 @@ function RefreshButton({ onRefresh }) {
   let Icon = loading ? Loading : RefreshArrow;
 
   return (
-    <Button bare style={{ padding: 10, marginRight: 5 }} onClick={_onRefresh}>
+    <Button
+      type="bare"
+      style={{ padding: 10, marginRight: 5 }}
+      onClick={_onRefresh}
+    >
       <Icon style={{ width: 18, height: 18 }} />
     </Button>
   );
@@ -307,7 +311,7 @@ function BudgetList({
         }}
       >
         <Button
-          bare
+          type="bare"
           style={{
             marginLeft: 10,
             color: colors.n4,
@@ -320,13 +324,14 @@ function BudgetList({
           Import file
         </Button>
 
-        <Button primary onClick={onCreate} style={{ marginLeft: 15 }}>
+        <Button type="primary" onClick={onCreate} style={{ marginLeft: 15 }}>
           Create new file
         </Button>
 
         {isNonProductionEnvironment() && (
           <Button
-            primary
+            type="primary"
+            isSubmit={false}
             onClick={() => onCreate({ testMode: true })}
             style={{ marginLeft: 15 }}
           >
diff --git a/packages/desktop-client/src/components/manager/ConfigServer.js b/packages/desktop-client/src/components/manager/ConfigServer.js
index 50f08f6a441cced84d035bdfe672a7f7d06f0411..b2dd63b68ee0bb1fbeb4ad48657c9b996739c1cf 100644
--- a/packages/desktop-client/src/components/manager/ConfigServer.js
+++ b/packages/desktop-client/src/components/manager/ConfigServer.js
@@ -139,13 +139,16 @@ export default function ConfigServer() {
           onChange={e => setUrl(e.target.value)}
           style={{ flex: 1, marginRight: 10 }}
         />
-        <ButtonWithLoading primary loading={loading} style={{ fontSize: 15 }}>
+        <ButtonWithLoading
+          type="primary"
+          loading={loading}
+          style={{ fontSize: 15 }}
+        >
           OK
         </ButtonWithLoading>
         {currentUrl && (
           <Button
-            bare
-            type="button"
+            type="bare"
             style={{ fontSize: 15, marginLeft: 10 }}
             onClick={() => navigate(-1)}
           >
@@ -163,14 +166,14 @@ export default function ConfigServer() {
         }}
       >
         {currentUrl ? (
-          <Button bare style={{ color: colors.n4 }} onClick={onSkip}>
+          <Button type="bare" style={{ color: colors.n4 }} onClick={onSkip}>
             Stop using a server
           </Button>
         ) : (
           <>
             {!isElectron() && (
               <Button
-                bare
+                type="bare"
                 style={{
                   color: colors.n4,
                   margin: 5,
@@ -182,7 +185,7 @@ export default function ConfigServer() {
               </Button>
             )}
             <Button
-              bare
+              type="bare"
               style={{ color: colors.n4, margin: 5 }}
               onClick={onSkip}
             >
@@ -191,7 +194,7 @@ export default function ConfigServer() {
 
             {isNonProductionEnvironment() && (
               <Button
-                primary
+                type="primary"
                 style={{ marginLeft: 15 }}
                 onClick={onCreateTestFile}
               >
diff --git a/packages/desktop-client/src/components/manager/DeleteFile.js b/packages/desktop-client/src/components/manager/DeleteFile.js
index fc783d097636ba0270ec698ed00fb4a687d6601d..36aafb99307f0fb67c02b01354d372a29330626f 100644
--- a/packages/desktop-client/src/components/manager/DeleteFile.js
+++ b/packages/desktop-client/src/components/manager/DeleteFile.js
@@ -56,7 +56,7 @@ export default function DeleteMenu({ modalProps, actions, file }) {
               </Text>
 
               <ButtonWithLoading
-                primary
+                type="primary"
                 loading={loadingState === 'cloud'}
                 style={{
                   backgroundColor: colors.r4,
@@ -98,7 +98,7 @@ export default function DeleteMenu({ modalProps, actions, file }) {
               )}
 
               <ButtonWithLoading
-                primary={!isRemote}
+                type={isRemote ? 'normal' : 'primary'}
                 loading={loadingState === 'local'}
                 style={[
                   {
diff --git a/packages/desktop-client/src/components/manager/ImportActual.js b/packages/desktop-client/src/components/manager/ImportActual.js
index ba2d460bd2bfc3bb906b85652c7c53ebcd9ac2ec..a4c66d7a9b56fbde7d18ae6c133ed500b6e712de 100644
--- a/packages/desktop-client/src/components/manager/ImportActual.js
+++ b/packages/desktop-client/src/components/manager/ImportActual.js
@@ -71,7 +71,11 @@ function Import({ modalProps }) {
             <P>Select one of these compressed files and import it here.</P>
 
             <View style={{ alignSelf: 'center' }}>
-              <ButtonWithLoading loading={importing} primary onClick={onImport}>
+              <ButtonWithLoading
+                type="primary"
+                loading={importing}
+                onClick={onImport}
+              >
                 Select file...
               </ButtonWithLoading>
             </View>
diff --git a/packages/desktop-client/src/components/manager/ImportYNAB4.js b/packages/desktop-client/src/components/manager/ImportYNAB4.js
index 7c2d9cd7aed1bbde1ebae052066dd1328ee229f9..ce4d1dbebe7b6a40495568be91ec5444e729748d 100644
--- a/packages/desktop-client/src/components/manager/ImportYNAB4.js
+++ b/packages/desktop-client/src/components/manager/ImportYNAB4.js
@@ -62,7 +62,11 @@ function Import({ modalProps }) {
               folder”. Upload the zipped folder for importing.
             </P>
             <View>
-              <ButtonWithLoading loading={importing} primary onClick={onImport}>
+              <ButtonWithLoading
+                type="primary"
+                loading={importing}
+                onClick={onImport}
+              >
                 Select zip file...
               </ButtonWithLoading>
             </View>
diff --git a/packages/desktop-client/src/components/manager/ImportYNAB5.js b/packages/desktop-client/src/components/manager/ImportYNAB5.js
index 302db9cae0bdd9b83919c65c7e1fe4ef381e3038..01cdc854ea081df6ce1b3608fbbb62f2a7ecbab7 100644
--- a/packages/desktop-client/src/components/manager/ImportYNAB5.js
+++ b/packages/desktop-client/src/components/manager/ImportYNAB5.js
@@ -75,7 +75,11 @@ function Import({ modalProps }) {
               problems.
             </P>
             <View>
-              <ButtonWithLoading loading={importing} primary onClick={onImport}>
+              <ButtonWithLoading
+                type="primary"
+                loading={importing}
+                onClick={onImport}
+              >
                 Select file...
               </ButtonWithLoading>
             </View>
diff --git a/packages/desktop-client/src/components/manager/WelcomeScreen.js b/packages/desktop-client/src/components/manager/WelcomeScreen.js
index 076bba6e63c549a4f92672570000b1d0eee69cd2..18e1b1bc404a95cf423bed0e352e3024adb12d61 100644
--- a/packages/desktop-client/src/components/manager/WelcomeScreen.js
+++ b/packages/desktop-client/src/components/manager/WelcomeScreen.js
@@ -59,7 +59,7 @@ function WelcomeScreen({ createBudget, pushModal }) {
         }}
       >
         <Button onClick={() => pushModal('import')}>Import my budget</Button>
-        <Button primary onClick={createBudget}>
+        <Button type="primary" onClick={createBudget}>
           Start fresh
         </Button>
       </View>
diff --git a/packages/desktop-client/src/components/manager/subscribe/Bootstrap.tsx b/packages/desktop-client/src/components/manager/subscribe/Bootstrap.tsx
index ff264ca56d584ff3e9067d865dcdeb7421bb7c26..49a0b89c60c37dfe4735ec54067889763087747c 100644
--- a/packages/desktop-client/src/components/manager/subscribe/Bootstrap.tsx
+++ b/packages/desktop-client/src/components/manager/subscribe/Bootstrap.tsx
@@ -82,7 +82,7 @@ export default function Bootstrap() {
       <ConfirmPasswordForm
         buttons={
           <Button
-            bare
+            type="bare"
             style={{ fontSize: 15, color: colors.b4, marginRight: 15 }}
             onClick={onDemo}
           >
diff --git a/packages/desktop-client/src/components/manager/subscribe/ChangePassword.tsx b/packages/desktop-client/src/components/manager/subscribe/ChangePassword.tsx
index b8ffeb0df3ca9b7ce218b73658d67dea145319c3..843616ea4b050edc7b3e8c3fd79bbef555292c67 100644
--- a/packages/desktop-client/src/components/manager/subscribe/ChangePassword.tsx
+++ b/packages/desktop-client/src/components/manager/subscribe/ChangePassword.tsx
@@ -83,8 +83,7 @@ export default function ChangePassword() {
       <ConfirmPasswordForm
         buttons={
           <Button
-            bare
-            type="button"
+            type="bare"
             style={{ fontSize: 15, marginRight: 10 }}
             onClick={() => navigate('/')}
           >
diff --git a/packages/desktop-client/src/components/manager/subscribe/ConfirmPasswordForm.tsx b/packages/desktop-client/src/components/manager/subscribe/ConfirmPasswordForm.tsx
index c049150eb6861dee98491871b3e6425b21eec5c4..1d7d36a5f8d462989d7412b997fa4975827822bc 100644
--- a/packages/desktop-client/src/components/manager/subscribe/ConfirmPasswordForm.tsx
+++ b/packages/desktop-client/src/components/manager/subscribe/ConfirmPasswordForm.tsx
@@ -73,7 +73,7 @@ export function ConfirmPasswordForm({ buttons, onSetPassword, onError }) {
         </label>
         <View style={{ flex: 1 }} />
         {buttons}
-        <ButtonWithLoading primary loading={loading}>
+        <ButtonWithLoading type="primary" loading={loading}>
           OK
         </ButtonWithLoading>
       </View>
diff --git a/packages/desktop-client/src/components/manager/subscribe/Login.tsx b/packages/desktop-client/src/components/manager/subscribe/Login.tsx
index 3347246b58212a6aa4037143b6d671067cfcebfc..e13e29fbba9abb04d64e5c96b63db855a1898508 100644
--- a/packages/desktop-client/src/components/manager/subscribe/Login.tsx
+++ b/packages/desktop-client/src/components/manager/subscribe/Login.tsx
@@ -95,7 +95,11 @@ export default function Login() {
           }
           style={{ flex: 1, marginRight: 10 }}
         />
-        <ButtonWithLoading primary loading={loading} style={{ fontSize: 15 }}>
+        <ButtonWithLoading
+          type="primary"
+          loading={loading}
+          style={{ fontSize: 15 }}
+        >
           Sign in
         </ButtonWithLoading>
       </form>
@@ -107,7 +111,7 @@ export default function Login() {
         }}
       >
         <Button
-          bare
+          type="bare"
           style={{ fontSize: 15, color: colors.b4, marginLeft: 10 }}
           onClick={onDemo}
         >
diff --git a/packages/desktop-client/src/components/modals/CloseAccount.js b/packages/desktop-client/src/components/modals/CloseAccount.js
index 8b75d62261d25edeb3cf72f6cdc283a9ab54a9b5..f8315bb73c10beef214f81a316b4235842639fa2 100644
--- a/packages/desktop-client/src/components/modals/CloseAccount.js
+++ b/packages/desktop-client/src/components/modals/CloseAccount.js
@@ -172,16 +172,10 @@ function CloseAccount({
                 justifyContent: 'flex-end',
               }}
             >
-              <Button
-                type="submit"
-                style={{ marginRight: 10 }}
-                onClick={modalProps.onClose}
-              >
+              <Button style={{ marginRight: 10 }} onClick={modalProps.onClose}>
                 Cancel
               </Button>
-              <Button type="submit" primary>
-                Close Account
-              </Button>
+              <Button type="primary">Close Account</Button>
             </View>
           </form>
         </View>
diff --git a/packages/desktop-client/src/components/modals/ConfirmCategoryDelete.js b/packages/desktop-client/src/components/modals/ConfirmCategoryDelete.js
index ae4b5b80267e82e820055ce69d96b5964437819d..c8b08018c06b3dbea890f466734acc251ae44b74 100644
--- a/packages/desktop-client/src/components/modals/ConfirmCategoryDelete.js
+++ b/packages/desktop-client/src/components/modals/ConfirmCategoryDelete.js
@@ -92,7 +92,7 @@ export default function ConfirmCategoryDelete({
             </View>
 
             <Button
-              primary
+              type="primary"
               onClick={() => {
                 if (!transferCategory) {
                   setError('required-transfer');
diff --git a/packages/desktop-client/src/components/modals/CreateAccount.js b/packages/desktop-client/src/components/modals/CreateAccount.js
index 322fa12e4a9f749bc22d13abfd353995b1693ca7..a674d84c9abd06684cf07c968cfd98289ee101e7 100644
--- a/packages/desktop-client/src/components/modals/CreateAccount.js
+++ b/packages/desktop-client/src/components/modals/CreateAccount.js
@@ -52,7 +52,7 @@ export default function CreateAccount({ modalProps, syncServerStatus }) {
         <View style={{ maxWidth: 500, gap: 30 }}>
           <View style={{ gap: 10 }}>
             <Button
-              primary
+              type="primary"
               style={{
                 padding: '10px 0',
                 fontSize: 15,
diff --git a/packages/desktop-client/src/components/modals/CreateEncryptionKey.js b/packages/desktop-client/src/components/modals/CreateEncryptionKey.js
index 687188bd25e849dd572665191e526ba46aeb7172..c0d10b1588fe44522a959dd59a41b31e8a9d6d5a 100644
--- a/packages/desktop-client/src/components/modals/CreateEncryptionKey.js
+++ b/packages/desktop-client/src/components/modals/CreateEncryptionKey.js
@@ -155,7 +155,7 @@ export default function CreateEncryptionKey({
             </View>
 
             <ModalButtons style={{ marginTop: 20 }}>
-              <ButtonWithLoading loading={loading} primary>
+              <ButtonWithLoading loading={loading} type="primary">
                 Enable
               </ButtonWithLoading>
             </ModalButtons>
diff --git a/packages/desktop-client/src/components/modals/CreateLocalAccount.js b/packages/desktop-client/src/components/modals/CreateLocalAccount.js
index 6bcec27c2dad035f5c7313e262063200041ed7db..e03dbd87bb29029d457ca61e39cfa27689c23f93 100644
--- a/packages/desktop-client/src/components/modals/CreateLocalAccount.js
+++ b/packages/desktop-client/src/components/modals/CreateLocalAccount.js
@@ -147,10 +147,8 @@ function CreateLocalAccount({ modalProps, actions }) {
             )}
 
             <ModalButtons>
-              <Button onClick={() => modalProps.onBack()} type="button">
-                Back
-              </Button>
-              <Button primary style={{ marginLeft: 10 }}>
+              <Button onClick={() => modalProps.onBack()}>Back</Button>
+              <Button type="primary" style={{ marginLeft: 10 }}>
                 Create
               </Button>
             </ModalButtons>
diff --git a/packages/desktop-client/src/components/modals/EditRule.js b/packages/desktop-client/src/components/modals/EditRule.js
index c3b40802d31e64078148e71ff6bb0c3d3840103a..e2333b96b7d572fc6299bdda6c3a81abf198c3b9 100644
--- a/packages/desktop-client/src/components/modals/EditRule.js
+++ b/packages/desktop-client/src/components/modals/EditRule.js
@@ -118,7 +118,7 @@ function EditorButtons({ onAdd, onDelete, style }) {
     <>
       {onDelete && (
         <Button
-          bare
+          type="bare"
           onClick={onDelete}
           style={{ padding: 7 }}
           aria-label="Delete entry"
@@ -128,7 +128,7 @@ function EditorButtons({ onAdd, onDelete, style }) {
       )}
       {onAdd && (
         <Button
-          bare
+          type="bare"
           onClick={onAdd}
           style={{ padding: 7 }}
           aria-label="Add entry"
@@ -380,7 +380,7 @@ function StageInfo() {
 function StageButton({ selected, children, style, onSelect }) {
   return (
     <Button
-      bare
+      type="bare"
       style={[
         { fontSize: 'inherit' },
         selected && {
@@ -898,7 +898,7 @@ export default function EditRule({
                 style={{ marginTop: 20 }}
               >
                 <Button onClick={() => modalProps.onClose()}>Cancel</Button>
-                <Button primary onClick={() => onSave()}>
+                <Button type="primary" onClick={() => onSave()}>
                   Save
                 </Button>
               </Stack>
diff --git a/packages/desktop-client/src/components/modals/FixEncryptionKey.js b/packages/desktop-client/src/components/modals/FixEncryptionKey.js
index c1062d8fcb2acc38f749f8dcce9f1a33e31e31a0..6fccc259b5050878a7d6c27276e78be1add5fc88 100644
--- a/packages/desktop-client/src/components/modals/FixEncryptionKey.js
+++ b/packages/desktop-client/src/components/modals/FixEncryptionKey.js
@@ -136,8 +136,8 @@ export default function FixEncryptionKey({
                 Back
               </Button>
               <ButtonWithLoading
+                type="primary"
                 loading={loading}
-                primary
                 onClick={onUpdateKey}
               >
                 {hasExistingKey ? 'Update key' : 'Create key'}
diff --git a/packages/desktop-client/src/components/modals/GoCardlessExternalMsg.js b/packages/desktop-client/src/components/modals/GoCardlessExternalMsg.js
index 47998eb282b9e469629baf4c4d46f89aaf7b2e91..2a764a76cf82ddbdae838132cba87b75843893e8 100644
--- a/packages/desktop-client/src/components/modals/GoCardlessExternalMsg.js
+++ b/packages/desktop-client/src/components/modals/GoCardlessExternalMsg.js
@@ -198,7 +198,7 @@ export default function GoCardlessExternalMsg({
 
         <View style={{ flexDirection: 'row', gap: 10, alignItems: 'center' }}>
           <Button
-            primary
+            type="primary"
             style={{
               padding: '10px 0',
               fontSize: 15,
@@ -210,7 +210,11 @@ export default function GoCardlessExternalMsg({
           >
             Link bank in browser &rarr;
           </Button>
-          <Button bare onClick={() => setMenuOpen(true)} aria-label="Menu">
+          <Button
+            type="bare"
+            onClick={() => setMenuOpen(true)}
+            aria-label="Menu"
+          >
             <DotsHorizontalTriple
               width={15}
               height={15}
@@ -285,7 +289,7 @@ export default function GoCardlessExternalMsg({
             </View>
           ) : success ? (
             <Button
-              primary
+              type="primary"
               style={{
                 padding: '10px 0',
                 fontSize: 15,
@@ -305,7 +309,7 @@ export default function GoCardlessExternalMsg({
               <P style={{ color: colors.r5 }}>
                 GoCardless integration has not yet been configured.
               </P>
-              <Button primary onClick={onGoCardlessInit}>
+              <Button type="primary" onClick={onGoCardlessInit}>
                 Configure GoCardless integration
               </Button>
             </>
diff --git a/packages/desktop-client/src/components/modals/GoCardlessInitialise.tsx b/packages/desktop-client/src/components/modals/GoCardlessInitialise.tsx
index 06612ae1d0156f1c8329ecd252b04c94858ffe29..c18a02ac7a945f8f02309d984fad0343a4a8d458 100644
--- a/packages/desktop-client/src/components/modals/GoCardlessInitialise.tsx
+++ b/packages/desktop-client/src/components/modals/GoCardlessInitialise.tsx
@@ -90,7 +90,11 @@ const GoCardlessInitialise = ({
       </View>
 
       <ModalButtons>
-        <ButtonWithLoading loading={isLoading} primary onClick={onSubmit}>
+        <ButtonWithLoading
+          type="primary"
+          loading={isLoading}
+          onClick={onSubmit}
+        >
           Save and continue
         </ButtonWithLoading>
       </ModalButtons>
diff --git a/packages/desktop-client/src/components/modals/ImportTransactions.js b/packages/desktop-client/src/components/modals/ImportTransactions.js
index 22b4c26839178085eb2cfe70968432433ae7355e..6a2387d5a204bcd7cb74aa59e5872508aa8d8ca5 100644
--- a/packages/desktop-client/src/components/modals/ImportTransactions.js
+++ b/packages/desktop-client/src/components/modals/ImportTransactions.js
@@ -994,7 +994,7 @@ export default function ImportTransactions({ modalProps, options }) {
           }}
         >
           <ButtonWithLoading
-            primary
+            type="primary"
             disabled={transactions.length === 0}
             loading={loadingState === 'importing'}
             onClick={onImport}
diff --git a/packages/desktop-client/src/components/modals/LoadBackup.js b/packages/desktop-client/src/components/modals/LoadBackup.js
index 1582822e16759119b09926b37da427a9f00bb605..a43e173c1eaffcf439ff67f3ac5bba2313d2bb44 100644
--- a/packages/desktop-client/src/components/modals/LoadBackup.js
+++ b/packages/desktop-client/src/components/modals/LoadBackup.js
@@ -88,7 +88,7 @@ function LoadBackup({
                   version below.
                 </Block>
                 <Button
-                  primary
+                  type="primary"
                   onClick={() => actions.loadBackup(budgetId, latestBackup.id)}
                 >
                   Revert to original version
@@ -105,7 +105,7 @@ function LoadBackup({
                   </Text>
                 </Block>
                 <Button
-                  primary
+                  type="primary"
                   disabled={backupDisabled}
                   onClick={() => actions.makeBackup()}
                 >
diff --git a/packages/desktop-client/src/components/modals/MergeUnusedPayees.js b/packages/desktop-client/src/components/modals/MergeUnusedPayees.js
index 32f61a6c4937dbbcfe67454da1ad0759572a0248..44bc4e2b52305a2ce27382ee3ff42cbc4e0f4617 100644
--- a/packages/desktop-client/src/components/modals/MergeUnusedPayees.js
+++ b/packages/desktop-client/src/components/modals/MergeUnusedPayees.js
@@ -159,10 +159,10 @@ export default function MergeUnusedPayees({
 
             <ModalButtons style={{ marginTop: 20 }} focusButton>
               <Button
-                primary
+                type="primary"
+                isSubmit={false}
                 style={{ marginRight: 10 }}
                 onClick={onMerge}
-                type="button"
               >
                 Merge
               </Button>
@@ -170,7 +170,6 @@ export default function MergeUnusedPayees({
                 <Button
                   style={{ marginRight: 10 }}
                   onClick={onMergeAndCreateRule}
-                  type="button"
                 >
                   Merge and edit rule
                 </Button>
@@ -178,7 +177,6 @@ export default function MergeUnusedPayees({
               <Button
                 style={{ marginRight: 10 }}
                 onClick={() => modalProps.onBack()}
-                type="button"
               >
                 Do nothing
               </Button>
diff --git a/packages/desktop-client/src/components/modals/PlaidExternalMsg.js b/packages/desktop-client/src/components/modals/PlaidExternalMsg.js
index ba9017c96660fac834c253c038de258d64cf7f41..b3266efca6c8cb9d52b4f6f0645952a1fe18b323 100644
--- a/packages/desktop-client/src/components/modals/PlaidExternalMsg.js
+++ b/packages/desktop-client/src/components/modals/PlaidExternalMsg.js
@@ -85,7 +85,7 @@ export default function PlaidExternalMsg({
             </View>
           ) : success ? (
             <Button
-              primary
+              type="primary"
               style={{
                 padding: '10px 0',
                 fontSize: 15,
@@ -100,7 +100,7 @@ export default function PlaidExternalMsg({
             </Button>
           ) : (
             <Button
-              primary
+              type="primary"
               style={{
                 padding: '10px 0',
                 fontSize: 15,
diff --git a/packages/desktop-client/src/components/modals/SelectLinkedAccounts.js b/packages/desktop-client/src/components/modals/SelectLinkedAccounts.js
index db7e13c199d897125c00f2d06098161e3b8ebedc..f7580f520bf12fbb297d828de8afb067eca4b40e 100644
--- a/packages/desktop-client/src/components/modals/SelectLinkedAccounts.js
+++ b/packages/desktop-client/src/components/modals/SelectLinkedAccounts.js
@@ -130,7 +130,7 @@ export default function SelectLinkedAccounts({
             }}
           >
             <Button
-              primary
+              type="primary"
               onClick={onNext}
               disabled={!Object.keys(chosenAccounts).length}
             >
@@ -195,7 +195,7 @@ function TableRow({
           </Button>
         ) : (
           <Button
-            primary
+            type="primary"
             onClick={() => {
               setFocusedField('account');
             }}
diff --git a/packages/desktop-client/src/components/payees/index.js b/packages/desktop-client/src/components/payees/index.js
index df3b7ad1b4cec0342178e40add230de559e4826a..6b763a4c0a7c1320b1eee72a622e5d83065acdb0 100644
--- a/packages/desktop-client/src/components/payees/index.js
+++ b/packages/desktop-client/src/components/payees/index.js
@@ -487,7 +487,7 @@ export const ManagePayees = forwardRef(
         >
           <View>
             <Button
-              bare
+              type="bare"
               style={{ marginRight: 10 }}
               disabled={buttonsDisabled}
               onClick={() => setMenuOpen(true)}
@@ -513,7 +513,7 @@ export const ManagePayees = forwardRef(
             {(orphanedOnly ||
               (orphanedPayees && orphanedPayees.length > 0)) && (
               <Button
-                bare
+                type="bare"
                 style={{ marginRight: 10 }}
                 onClick={() => {
                   setOrphanedOnly(!orphanedOnly);
diff --git a/packages/desktop-client/src/components/reports/Header.js b/packages/desktop-client/src/components/reports/Header.js
index 70dc7d054ca91939ebd4eca72b6f65069e89da7f..c83d21d4792278afe9b2ae453377666d825a6157 100644
--- a/packages/desktop-client/src/components/reports/Header.js
+++ b/packages/desktop-client/src/components/reports/Header.js
@@ -67,8 +67,8 @@ function Header({
       }}
     >
       <ButtonLink
+        type="bare"
         to="/reports"
-        bare
         style={{ marginBottom: '15', alignSelf: 'flex-start' }}
       >
         <ArrowLeft width={10} height={10} style={{ marginRight: 5 }} /> Back
@@ -113,20 +113,29 @@ function Header({
         <FilterButton onApply={onApply} />
 
         {show1Month && (
-          <Button bare onClick={() => onChangeDates(...getLatestRange(1))}>
+          <Button
+            type="bare"
+            onClick={() => onChangeDates(...getLatestRange(1))}
+          >
             1 month
           </Button>
         )}
-        <Button bare onClick={() => onChangeDates(...getLatestRange(2))}>
+        <Button type="bare" onClick={() => onChangeDates(...getLatestRange(2))}>
           3 months
         </Button>
-        <Button bare onClick={() => onChangeDates(...getLatestRange(5))}>
+        <Button type="bare" onClick={() => onChangeDates(...getLatestRange(5))}>
           6 months
         </Button>
-        <Button bare onClick={() => onChangeDates(...getLatestRange(11))}>
+        <Button
+          type="bare"
+          onClick={() => onChangeDates(...getLatestRange(11))}
+        >
           1 Year
         </Button>
-        <Button bare onClick={() => onChangeDates(...getFullRange(allMonths))}>
+        <Button
+          type="bare"
+          onClick={() => onChangeDates(...getFullRange(allMonths))}
+        >
           All Time
         </Button>
       </View>
diff --git a/packages/desktop-client/src/components/schedules/DiscoverSchedules.js b/packages/desktop-client/src/components/schedules/DiscoverSchedules.js
index bea585f1eb34acc50f03c25267b70aa48263ea9e..df03567842284656dbfd8afc8c5834b05f214cba 100644
--- a/packages/desktop-client/src/components/schedules/DiscoverSchedules.js
+++ b/packages/desktop-client/src/components/schedules/DiscoverSchedules.js
@@ -181,7 +181,7 @@ export default function DiscoverSchedules() {
         }}
       >
         <ButtonWithLoading
-          primary
+          type="primary"
           loading={creating}
           disabled={selectedInst.items.size === 0}
           onClick={onCreate}
diff --git a/packages/desktop-client/src/components/schedules/EditSchedule.js b/packages/desktop-client/src/components/schedules/EditSchedule.js
index 8a9176e976f2d37e6bf1341f58e785e41def3439..ba4091d3d28098590853cabdf5f08b869f4253d4 100644
--- a/packages/desktop-client/src/components/schedules/EditSchedule.js
+++ b/packages/desktop-client/src/components/schedules/EditSchedule.js
@@ -686,7 +686,7 @@ export default function ScheduleDetails() {
           ) : (
             <View style={{ flexDirection: 'row', alignItems: 'center' }}>
               <Button
-                bare
+                type="bare"
                 style={{
                   color:
                     state.transactionsMode === 'linked' ? colors.b4 : colors.n7,
@@ -698,7 +698,7 @@ export default function ScheduleDetails() {
                 Linked transactions
               </Button>{' '}
               <Button
-                bare
+                type="bare"
                 style={{
                   color:
                     state.transactionsMode === 'matched'
@@ -772,7 +772,7 @@ export default function ScheduleDetails() {
         <Button style={{ marginRight: 10 }} onClick={() => navigate(-1)}>
           Cancel
         </Button>
-        <Button primary onClick={onSave}>
+        <Button type="primary" onClick={onSave}>
           {adding ? 'Add' : 'Save'}
         </Button>
       </Stack>
diff --git a/packages/desktop-client/src/components/schedules/PostsOfflineNotification.js b/packages/desktop-client/src/components/schedules/PostsOfflineNotification.js
index 43a6b19f245cda7b2a9e342b0bd5f5e9297500b0..34a6f03ee927354843f3a8a291d1d9dfd32f7070 100644
--- a/packages/desktop-client/src/components/schedules/PostsOfflineNotification.js
+++ b/packages/desktop-client/src/components/schedules/PostsOfflineNotification.js
@@ -71,7 +71,7 @@ export default function PostsOfflineNotification() {
         spacing={2}
       >
         <Button onClick={onClose}>Decide later</Button>
-        <Button primary onClick={onPost}>
+        <Button type="primary" onClick={onPost}>
           Post transactions
         </Button>
       </Stack>
diff --git a/packages/desktop-client/src/components/schedules/SchedulesTable.js b/packages/desktop-client/src/components/schedules/SchedulesTable.js
index efff12ccf6dd704016186bb89f07d5cc9280afb8..1852588477ffdba3d005d38dbe3b3efac5e9bfb7 100644
--- a/packages/desktop-client/src/components/schedules/SchedulesTable.js
+++ b/packages/desktop-client/src/components/schedules/SchedulesTable.js
@@ -24,7 +24,7 @@ function OverflowMenu({ schedule, status, onAction }) {
   return (
     <View>
       <Button
-        bare
+        type="bare"
         onClick={e => {
           e.stopPropagation();
           setOpen(true);
diff --git a/packages/desktop-client/src/components/schedules/index.js b/packages/desktop-client/src/components/schedules/index.js
index 90bc38270be07438bdbf5e4c0051ba3ab840e6f6..e8f04581f9235e85c8cf776cdb0a02d5d2aa045f 100644
--- a/packages/desktop-client/src/components/schedules/index.js
+++ b/packages/desktop-client/src/components/schedules/index.js
@@ -95,7 +95,7 @@ export default function Schedules() {
         }}
       >
         <Button onClick={onDiscover}>Find schedules</Button>
-        <Button primary onClick={onAdd}>
+        <Button type="primary" onClick={onAdd}>
           Add new schedule
         </Button>
       </View>
diff --git a/packages/desktop-client/src/components/select/RecurringSchedulePicker.js b/packages/desktop-client/src/components/select/RecurringSchedulePicker.js
index 2f5533350229e3b2d65fccfaea09f4aa5dc848b8..89dc7439e7aab653e21791361f44c33837f1afd0 100644
--- a/packages/desktop-client/src/components/select/RecurringSchedulePicker.js
+++ b/packages/desktop-client/src/components/select/RecurringSchedulePicker.js
@@ -221,7 +221,7 @@ function MonthlyPatterns({ config, dispatch }) {
             style={{ borderWidth: 1, width: '100%' }}
           />
           <Button
-            bare
+            type="bare"
             style={{ padding: 7 }}
             onClick={() =>
               dispatch({
@@ -233,7 +233,7 @@ function MonthlyPatterns({ config, dispatch }) {
             <SubtractIcon style={{ width: 8, height: 8 }} />
           </Button>
           <Button
-            bare
+            type="bare"
             style={{ padding: 7, marginLeft: 5 }}
             onClick={() => dispatch({ type: 'add-recurrence' })}
           >
@@ -343,8 +343,8 @@ function RecurringScheduleTooltip({ config: currentConfig, onClose, onSave }) {
       >
         <Button onClick={onClose}>Cancel</Button>
         <Button
+          type="primary"
           onClick={() => onSave(unparseConfig(config))}
-          primary
           style={{ marginLeft: 10 }}
         >
           Apply
diff --git a/packages/desktop-client/src/components/sidebar.js b/packages/desktop-client/src/components/sidebar.js
index b2c7d2f29326084dc3b7173c40245c8e15d82268..51d5f501f68c64123ba93693aa3b4eb389d222b8 100644
--- a/packages/desktop-client/src/components/sidebar.js
+++ b/packages/desktop-client/src/components/sidebar.js
@@ -445,7 +445,7 @@ function ToggleButton({ style, isFloating, onFloat }) {
       className="float"
       style={[style, { flexShrink: 0, color: colors.n5 }]}
     >
-      <Button bare onClick={onFloat}>
+      <Button type="bare" onClick={onFloat}>
         {isFloating ? (
           <Pin
             style={{
diff --git a/packages/desktop-client/src/components/table.tsx b/packages/desktop-client/src/components/table.tsx
index b4a63e243181dcf5803291b1676bcf4db77c52ce..d505a2299f58e4946f33addef5198fe229a4c184 100644
--- a/packages/desktop-client/src/components/table.tsx
+++ b/packages/desktop-client/src/components/table.tsx
@@ -872,7 +872,7 @@ export function SelectedItemsButton({ name, keyHandlers, items, onSelect }) {
       <KeyHandlers keys={keyHandlers || {}} />
 
       <Button
-        bare
+        type="bare"
         style={{ color: colors.b3 }}
         onClick={() => setMenuOpen(true)}
       >
diff --git a/packages/desktop-client/src/components/transactions/TransactionsTable.js b/packages/desktop-client/src/components/transactions/TransactionsTable.js
index c44d0e95aedfc935e44d9fc5715699a020b12910..5664a95077d897a82c8f1fd0525b4ae03c2656c8 100644
--- a/packages/desktop-client/src/components/transactions/TransactionsTable.js
+++ b/packages/desktop-client/src/components/transactions/TransactionsTable.js
@@ -490,7 +490,7 @@ function HeaderCell({
       alignItems={alignItems}
       unexposedContent={
         <Button
-          bare
+          type="bare"
           onClick={onClick}
           style={{
             whiteSpace: 'nowrap',
@@ -644,7 +644,7 @@ function PayeeIcons({
 
   return schedule ? (
     <Button
-      bare
+      type="bare"
       style={buttonStyle}
       onClick={e => {
         e.stopPropagation();
@@ -659,7 +659,7 @@ function PayeeIcons({
     </Button>
   ) : transferAccount ? (
     <Button
-      bare
+      type="bare"
       style={buttonStyle}
       onClick={e => {
         e.stopPropagation();
@@ -1276,8 +1276,8 @@ function TransactionError({ error, isDeposit, onAddSplit, style }) {
             </Text>
             <View style={{ flex: 1 }} />
             <Button
+              type="primary"
               style={{ marginLeft: 15, padding: '4px 10px' }}
-              primary
               onClick={onAddSplit}
             >
               Add Split
@@ -1416,8 +1416,8 @@ function NewTransaction({
           />
         ) : (
           <Button
+            type="primary"
             style={{ padding: '4px 10px' }}
-            primary
             onClick={onAdd}
             data-testid="add-button"
           >
diff --git a/packages/desktop-client/src/components/util/AmountInput.js b/packages/desktop-client/src/components/util/AmountInput.js
index 1501f58bc69f5a19d280d5b6e5fb1d5748c5bd5a..74ea84acbb43a7c6a3f6cf45fe67abaf8b84a8d6 100644
--- a/packages/desktop-client/src/components/util/AmountInput.js
+++ b/packages/desktop-client/src/components/util/AmountInput.js
@@ -29,7 +29,7 @@ export function AmountInput({ id, defaultValue = 0, onChange, style }) {
     <InputWithContent
       id={id}
       leftContent={
-        <Button bare style={{ padding: '0 7px' }} onClick={onSwitch}>
+        <Button type="bare" style={{ padding: '0 7px' }} onClick={onSwitch}>
           {negative ? (
             <Subtract style={{ width: 8, height: 8 }} />
           ) : (
diff --git a/packages/desktop-client/src/style/theme.tsx b/packages/desktop-client/src/style/theme.tsx
index e2ec92f305589c530914efe6c2ffd37aef1a416e..6f349bee11049adba74cf1e38be55cd49be7605f 100644
--- a/packages/desktop-client/src/style/theme.tsx
+++ b/packages/desktop-client/src/style/theme.tsx
@@ -1,16 +1,13 @@
 import { useSelector } from 'react-redux';
 
 import type { Theme } from 'loot-core/src/client/state-types/prefs';
-import { isNonProductionEnvironment } from 'loot-core/src/shared/environment';
 
 import * as darkTheme from './themes/dark';
-import * as developmentTheme from './themes/development';
 import * as lightTheme from './themes/light';
 
 const themes = {
   light: lightTheme,
   dark: darkTheme,
-  ...(isNonProductionEnvironment() && { development: developmentTheme }),
 };
 
 export const themeNames = Object.keys(themes) as Theme[];
diff --git a/packages/desktop-client/src/style/themes/dark.ts b/packages/desktop-client/src/style/themes/dark.ts
index 19b70926483d46d1e3d9ceb15ea197af8854788a..40b7e3edf3f98f68f947631658ba4ef6b903886a 100644
--- a/packages/desktop-client/src/style/themes/dark.ts
+++ b/packages/desktop-client/src/style/themes/dark.ts
@@ -64,27 +64,50 @@ export const altMenuItemTextSelected = colorPalette.navy150;
 export const altMenuItemTextHeader = colorPalette.purple500;
 export const altMenuBorder = colorPalette.navy200;
 export const altMenuBorderHover = colorPalette.purple400;
-export const buttonAltMenuText = colorPalette.navy150;
-export const buttonAltMenuTextHover = colorPalette.navy100;
-export const buttonAltMenuTextSelected = colorPalette.navy100;
-export const buttonAltMenuBackground = colorPalette.navy800;
-export const buttonAltMenuBackgroundHover = colorPalette.navy600;
-export const buttonAltMenuBorder = colorPalette.navy600;
-export const buttonPositiveText = colorPalette.black;
-export const buttonPositiveTextHover = colorPalette.navy150;
-export const buttonPositiveTextSelected = colorPalette.black;
-export const buttonPositiveBackground = colorPalette.purple400;
-export const buttonPositiveBackgroundHover = colorPalette.navy800;
-export const buttonPositiveBorder = colorPalette.purple400;
-export const buttonNeutralText = colorPalette.navy150;
-export const buttonNeutralTextHover = colorPalette.navy150;
-export const buttonNeutralBackground = colorPalette.navy800;
-export const buttonNeutralBackgroundHover = colorPalette.navy600;
-export const buttonNeutralBorder = colorPalette.navy300;
-export const buttonDisabledText = colorPalette.navy500;
-export const buttonDisabledBackground = colorPalette.navy800;
-export const buttonDisabledBorder = colorPalette.navy500;
-export const buttonShadow = colorPalette.navy700;
+
+// Button
+export const buttonMenuText = colorPalette.navy100;
+export const buttonMenuTextHover = colorPalette.navy50;
+export const buttonMenuBackground = 'transparent';
+export const buttonMenuBackgroundHover = 'rgba(200, 200, 200, .25)';
+export const buttonMenuBorder = colorPalette.navy500;
+
+export const buttonMenuSelectedText = colorPalette.green800;
+export const buttonMenuSelectedTextHover = colorPalette.orange800;
+export const buttonMenuSelectedBackground = colorPalette.orange200;
+export const buttonMenuSelectedBackgroundHover = colorPalette.orange300;
+export const buttonMenuSelectedBorder = buttonMenuSelectedBackground;
+
+export const buttonPrimaryText = colorPalette.white;
+export const buttonPrimaryTextHover = buttonPrimaryText;
+export const buttonPrimaryBackground = colorPalette.purple400;
+export const buttonPrimaryBackgroundHover = buttonPrimaryBackground;
+export const buttonPrimaryBorder = buttonPrimaryBackground;
+export const buttonPrimaryShadow = 'rgba(0, 0, 0, 0.6)';
+
+export const buttonPrimaryDisabledText = colorPalette.navy700;
+export const buttonPrimaryDisabledBackground = colorPalette.navy400;
+export const buttonPrimaryDisabledBorder = buttonPrimaryDisabledBackground;
+
+export const buttonNormalText = colorPalette.navy150;
+export const buttonNormalTextHover = colorPalette.navy150;
+export const buttonNormalBackground = colorPalette.navy800;
+export const buttonNormalBackgroundHover = colorPalette.navy600;
+export const buttonNormalBorder = colorPalette.navy300;
+export const buttonNormalShadow = 'rgba(0, 0, 0, 0.4)';
+
+export const buttonNormalDisabledText = colorPalette.navy500;
+export const buttonNormalDisabledBackground = colorPalette.navy800;
+export const buttonNormalDisabledBorder = colorPalette.navy500;
+
+export const buttonBareText = buttonNormalText;
+export const buttonBareTextHover = buttonNormalText;
+export const buttonBareBackground = 'transparent';
+export const buttonBareBackgroundHover = 'rgba(200, 200, 200, .3)';
+export const buttonBareBackgroundActive = 'rgba(200, 200, 200, .5)';
+export const buttonBareDisabledText = buttonNormalDisabledText;
+export const buttonBareDisabledBackground = buttonBareBackground;
+
 export const noticeBackground = colorPalette.green800;
 export const noticeText = colorPalette.green300;
 export const noticeAccent = colorPalette.green500;
diff --git a/packages/desktop-client/src/style/themes/development.ts b/packages/desktop-client/src/style/themes/development.ts
deleted file mode 100644
index 1e8f39d40b3b399adcedc1928e9e2df5cb6ad048..0000000000000000000000000000000000000000
--- a/packages/desktop-client/src/style/themes/development.ts
+++ /dev/null
@@ -1,115 +0,0 @@
-import * as colorPalette from '../palette';
-
-export const pageBackground = colorPalette.blue600;
-export const pageBackgroundModalActive = colorPalette.blue700;
-export const pageBackgroundTopLeft = colorPalette.green300;
-export const pageBackgroundBottomRight = colorPalette.red600;
-export const pageBackgroundLineTop = colorPalette.navy50;
-export const pageBackgroundLineMid = colorPalette.green500;
-export const pageBackgroundLineBottom = colorPalette.orange200;
-export const pageText = colorPalette.blue300;
-export const pageTextSubdued = colorPalette.blue500;
-export const pageTextPositive = colorPalette.blue50;
-export const pageTextLink = colorPalette.blue400;
-export const modalBackground = colorPalette.navy900;
-export const modalBorder = colorPalette.navy200;
-export const cardBackground = colorPalette.purple700;
-export const cardBorder = colorPalette.purple400;
-export const cardShadow = colorPalette.purple100;
-export const tableBackground = colorPalette.red900;
-export const tableRowBackgroundHover = colorPalette.red800;
-export const tableText = colorPalette.red200;
-export const tableTextSelected = colorPalette.red150;
-export const tableTextHover = colorPalette.red400;
-export const tableTextEditing = colorPalette.black;
-export const tableTextEditingBackground = colorPalette.red200;
-export const tableTextInactive = colorPalette.red500;
-export const tableHeaderText = colorPalette.red700;
-export const tableHeaderBackground = colorPalette.red300;
-export const tableBorder = colorPalette.red200;
-export const tableBorderSelected = colorPalette.purple400;
-export const tableBorderHover = colorPalette.purple300;
-export const tableBorderSeparator = colorPalette.navy400;
-export const tableRowBackgroundHighlight = colorPalette.red700;
-export const tableRowBackgroundHighlightText = colorPalette.red200;
-export const tableRowHeaderBackground = colorPalette.red100;
-export const tableRowHeaderText = colorPalette.red700;
-export const sidebarBackground = colorPalette.orange800;
-export const sidebarItemBackground = colorPalette.orange700;
-export const sidebarItemBackgroundSelected = colorPalette.orange900;
-export const sidebarItemBackgroundHover = colorPalette.orange500;
-export const sidebarItemAccent = colorPalette.orange200;
-export const sidebarItemAccentSelected = colorPalette.orange400;
-export const sidebarItemAccentHover = colorPalette.orange200;
-export const sidebarItemText = colorPalette.orange200;
-export const sidebarItemTextSelected = colorPalette.orange400;
-export const sidebarItemTextHover = colorPalette.orange150;
-export const tooltipBackground = colorPalette.white;
-export const tooltipBorder = colorPalette.black;
-export const menuBackground = colorPalette.green800;
-export const menuItemBackground = colorPalette.green700;
-export const menuItemBackgroundHover = colorPalette.green500;
-export const menuItemText = colorPalette.green200;
-export const menuItemTextHover = colorPalette.green50;
-export const menuItemTextSelected = colorPalette.green500;
-export const menuItemTextHeader = colorPalette.green300;
-export const menuBorder = colorPalette.green500;
-export const menuBorderHover = colorPalette.green900;
-export const altMenuBackground = colorPalette.navy700;
-export const altMenuItemBackground = colorPalette.navy700;
-export const altMenuItemBackgroundHover = colorPalette.navy600;
-export const altMenuItemText = colorPalette.navy150;
-export const altMenuItemTextHover = colorPalette.navy150;
-export const altMenuItemTextSelected = colorPalette.navy150;
-export const altMenuItemTextHeader = colorPalette.purple500;
-export const altMenuBorder = colorPalette.navy200;
-export const altMenuBorderHover = colorPalette.purple400;
-export const buttonAltMenuText = colorPalette.navy150;
-export const buttonAltMenuTextHover = colorPalette.navy100;
-export const buttonAltMenuTextSelected = colorPalette.navy100;
-export const buttonAltMenuBackground = colorPalette.navy800;
-export const buttonAltMenuBackgroundHover = colorPalette.navy600;
-export const buttonAltMenuBorder = colorPalette.navy600;
-export const buttonPositiveText = colorPalette.purple200;
-export const buttonPositiveTextHover = colorPalette.purple50;
-export const buttonPositiveTextSelected = colorPalette.purple600;
-export const buttonPositiveBackground = colorPalette.purple400;
-export const buttonPositiveBackgroundHover = colorPalette.purple800;
-export const buttonPositiveBorder = colorPalette.purple700;
-export const buttonNeutralText = colorPalette.navy50;
-export const buttonNeutralTextHover = colorPalette.navy200;
-export const buttonNeutralBackground = colorPalette.navy400;
-export const buttonNeutralBackgroundHover = colorPalette.navy500;
-export const buttonNeutralBorder = colorPalette.navy800;
-export const buttonDisabledText = colorPalette.navy500;
-export const buttonDisabledBackground = colorPalette.navy800;
-export const buttonDisabledBorder = colorPalette.navy500;
-export const buttonShadow = colorPalette.navy700;
-export const noticeBackground = colorPalette.green800;
-export const noticeText = colorPalette.green300;
-export const noticeAccent = colorPalette.green500;
-export const warningBackground = colorPalette.orange800;
-export const warningText = colorPalette.orange200;
-export const warningAccent = colorPalette.orange500;
-export const errorBackground = colorPalette.red800;
-export const errorText = colorPalette.red200;
-export const errorAccent = colorPalette.red500;
-export const formLabelText = colorPalette.purple200;
-export const formInputBackground = colorPalette.purple700;
-export const formInputBackgroundSelected = colorPalette.purple400;
-export const formInputBackgroundSelection = colorPalette.purple400;
-export const formInputBorder = colorPalette.purple600;
-export const formInputTextReadOnlySelection = colorPalette.purple800;
-export const formInputBorderSelected = colorPalette.purple100;
-export const formInputText = colorPalette.purple150;
-export const formInputTextSelected = colorPalette.purple800;
-export const formInputTextPlaceholder = colorPalette.navy150;
-export const formInputTextSelection = colorPalette.navy800;
-export const formInputShadowSelected = colorPalette.purple400;
-export const formInputTextHighlight = colorPalette.purple400;
-export const pillBackground = colorPalette.green800;
-export const pillText = colorPalette.green600;
-export const pillBorder = colorPalette.green200;
-export const pillBackgroundSelected = colorPalette.green100;
-export const pillTextSelected = colorPalette.green700;
-export const pillBorderSelected = colorPalette.green900;
diff --git a/packages/desktop-client/src/style/themes/light.ts b/packages/desktop-client/src/style/themes/light.ts
index 2a029a24196b22cd6a4bfc11e541fa0208772e15..03fd08480db33bd93f9db67639022701d85c21a5 100644
--- a/packages/desktop-client/src/style/themes/light.ts
+++ b/packages/desktop-client/src/style/themes/light.ts
@@ -64,27 +64,50 @@ export const altMenuItemTextSelected = colorPalette.purple300;
 export const altMenuItemTextHeader = colorPalette.purple300;
 export const altMenuBorder = colorPalette.blue700;
 export const altMenuBorderHover = colorPalette.purple300;
-export const buttonAltMenuText = colorPalette.navy100;
-export const buttonAltMenuTextHover = colorPalette.navy50;
-export const buttonAltMenuTextSelected = colorPalette.navy50;
-export const buttonAltMenuBackground = colorPalette.blue800;
-export const buttonAltMenuBackgroundHover = colorPalette.blue700;
-export const buttonAltMenuBorder = colorPalette.navy200;
-export const buttonPositiveText = colorPalette.navy50;
-export const buttonPositiveTextHover = colorPalette.purple600;
-export const buttonPositiveTextSelected = colorPalette.navy50;
-export const buttonPositiveBackground = colorPalette.purple600;
-export const buttonPositiveBackgroundHover = colorPalette.navy50;
-export const buttonPositiveBorder = colorPalette.purple600;
-export const buttonNeutralText = colorPalette.navy700;
-export const buttonNeutralTextHover = colorPalette.navy800;
-export const buttonNeutralBackground = colorPalette.navy50;
-export const buttonNeutralBackgroundHover = colorPalette.navy100;
-export const buttonNeutralBorder = colorPalette.navy200;
-export const buttonDisabledText = colorPalette.navy300;
-export const buttonDisabledBackground = colorPalette.navy50;
-export const buttonDisabledBorder = colorPalette.navy300;
-export const buttonShadow = colorPalette.purple500;
+
+// Button
+export const buttonMenuText = colorPalette.navy100;
+export const buttonMenuTextHover = colorPalette.navy50;
+export const buttonMenuBackground = 'transparent';
+export const buttonMenuBackgroundHover = 'rgba(200, 200, 200, .25)';
+export const buttonMenuBorder = colorPalette.navy500;
+
+export const buttonMenuSelectedText = colorPalette.green800;
+export const buttonMenuSelectedTextHover = colorPalette.orange800;
+export const buttonMenuSelectedBackground = colorPalette.orange200;
+export const buttonMenuSelectedBackgroundHover = colorPalette.orange300;
+export const buttonMenuSelectedBorder = buttonMenuSelectedBackground;
+
+export const buttonPrimaryText = colorPalette.white;
+export const buttonPrimaryTextHover = buttonPrimaryText;
+export const buttonPrimaryBackground = colorPalette.purple500;
+export const buttonPrimaryBackgroundHover = buttonPrimaryBackground;
+export const buttonPrimaryBorder = buttonPrimaryBackground;
+export const buttonPrimaryShadow = 'rgba(0, 0, 0, 0.3)';
+
+export const buttonPrimaryDisabledText = colorPalette.white;
+export const buttonPrimaryDisabledBackground = colorPalette.navy300;
+export const buttonPrimaryDisabledBorder = buttonPrimaryDisabledBackground;
+
+export const buttonNormalText = colorPalette.navy900;
+export const buttonNormalTextHover = buttonNormalText;
+export const buttonNormalBackground = colorPalette.white;
+export const buttonNormalBackgroundHover = buttonNormalBackground;
+export const buttonNormalBorder = colorPalette.navy150;
+export const buttonNormalShadow = 'rgba(0, 0, 0, 0.2)';
+
+export const buttonNormalDisabledText = colorPalette.navy400;
+export const buttonNormalDisabledBackground = buttonNormalBackground;
+export const buttonNormalDisabledBorder = buttonNormalBorder;
+
+export const buttonBareText = buttonNormalText;
+export const buttonBareTextHover = buttonNormalText;
+export const buttonBareBackground = 'transparent';
+export const buttonBareBackgroundHover = 'rgba(100, 100, 100, .15)';
+export const buttonBareBackgroundActive = 'rgba(100, 100, 100, .25)';
+export const buttonBareDisabledText = buttonNormalDisabledText;
+export const buttonBareDisabledBackground = buttonBareBackground;
+
 export const noticeBackground = colorPalette.green50;
 export const noticeText = colorPalette.green500;
 export const noticeAccent = colorPalette.green200;
diff --git a/packages/loot-core/src/client/state-types/prefs.d.ts b/packages/loot-core/src/client/state-types/prefs.d.ts
index dad0df89a71872a477cb9335628ad51e29191584..7611242dc0d882cf6a3a0c65bed955c9b1758b8b 100644
--- a/packages/loot-core/src/client/state-types/prefs.d.ts
+++ b/packages/loot-core/src/client/state-types/prefs.d.ts
@@ -47,7 +47,7 @@ export type LocalPrefs = NullableValues<
   } & Record<`flags.${FeatureFlag}`, boolean>
 >;
 
-export type Theme = 'light' | 'dark' | 'development';
+export type Theme = 'light' | 'dark';
 export type GlobalPrefs = NullableValues<{
   floatingSidebar: boolean;
   maxMonths: number;
diff --git a/packages/loot-core/src/server/main.ts b/packages/loot-core/src/server/main.ts
index 26966dde210b65a12fbb4f10d89dce3e99325748..a46ad4e9ad930d99b3b34760d9b944f3b2e8f77e 100644
--- a/packages/loot-core/src/server/main.ts
+++ b/packages/loot-core/src/server/main.ts
@@ -1500,10 +1500,7 @@ handlers['load-global-prefs'] = async function () {
     autoUpdate: autoUpdate == null || autoUpdate === 'true' ? true : false,
     documentDir: documentDir || getDefaultDocumentDir(),
     keyId: encryptKey && JSON.parse(encryptKey).id,
-    theme:
-      theme === 'light' || theme === 'dark' || theme === 'development'
-        ? theme
-        : 'light',
+    theme: theme === 'light' || theme === 'dark' ? theme : 'light',
   };
 };
 
diff --git a/upcoming-release-notes/1395.md b/upcoming-release-notes/1395.md
new file mode 100644
index 0000000000000000000000000000000000000000..e9821ac8973964592ab173a1e543fbe34c4ed45c
--- /dev/null
+++ b/upcoming-release-notes/1395.md
@@ -0,0 +1,6 @@
+---
+category: Maintenance
+authors: [j-f1]
+---
+
+Refactor the button component a bit and enable dark mode for it