From 16df116d1dceeb2c9603564249895341292a99c9 Mon Sep 17 00:00:00 2001 From: Matiss Janis Aboltins Date: Sun, 14 Apr 2024 11:30:57 +0200 Subject: [PATCH] :recycle: (tooltip) migration to react-aria (vol 2) (#2593) --- .../src/components/LoggedInUser.tsx | 48 +++++----- .../src/components/NotesButton.tsx | 6 +- .../src/components/ThemeSelector.tsx | 53 ++++++----- .../src/components/Titlebar.tsx | 88 +++++++++---------- .../components/accounts/AccountSyncCheck.jsx | 63 +++++++------ .../src/components/common/Popover.tsx | 17 ++++ .../src/components/sidebar/Sidebar.tsx | 34 +++---- upcoming-release-notes/2593.md | 6 ++ 8 files changed, 173 insertions(+), 142 deletions(-) create mode 100644 packages/desktop-client/src/components/common/Popover.tsx create mode 100644 upcoming-release-notes/2593.md diff --git a/packages/desktop-client/src/components/LoggedInUser.tsx b/packages/desktop-client/src/components/LoggedInUser.tsx index f1043b764d..c9eba0badb 100644 --- a/packages/desktop-client/src/components/LoggedInUser.tsx +++ b/packages/desktop-client/src/components/LoggedInUser.tsx @@ -1,5 +1,5 @@ // @ts-strict-ignore -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import { useSelector } from 'react-redux'; import { type State } from 'loot-core/src/client/state-types'; @@ -9,10 +9,10 @@ import { theme, styles, type CSSProperties } from '../style'; import { Button } from './common/Button'; import { Menu } from './common/Menu'; +import { Popover } from './common/Popover'; import { Text } from './common/Text'; import { View } from './common/View'; import { useServerURL } from './ServerContext'; -import { Tooltip } from './tooltips'; type LoggedInUserProps = { hideIfNoServer?: boolean; @@ -29,6 +29,7 @@ export function LoggedInUser({ const [loading, setLoading] = useState(true); const [menuOpen, setMenuOpen] = useState(false); const serverUrl = useServerURL(); + const triggerRef = useRef(null); useEffect(() => { getUserData().then(() => setLoading(false)); @@ -95,6 +96,7 @@ export function LoggedInUser({ return ( - {menuOpen && ( - setMenuOpen(false)} - > - setMenuOpen(false)} + > + - - )} + serverUrl && { name: 'sign-out', text: 'Sign out' }, + { + name: 'config-server', + text: serverUrl ? 'Change server URL' : 'Start using a server', + }, + ]} + /> + ); } diff --git a/packages/desktop-client/src/components/NotesButton.tsx b/packages/desktop-client/src/components/NotesButton.tsx index 31868f5212..f39af29506 100644 --- a/packages/desktop-client/src/components/NotesButton.tsx +++ b/packages/desktop-client/src/components/NotesButton.tsx @@ -1,5 +1,4 @@ import React, { useEffect, useRef, useState, type ComponentProps } from 'react'; -import { Popover } from 'react-aria-components'; import { useLiveQuery } from 'loot-core/src/client/query-hooks'; import { send } from 'loot-core/src/platform/client/fetch'; @@ -7,9 +6,10 @@ import { q } from 'loot-core/src/shared/query'; import { type NoteEntity } from 'loot-core/types/models'; import { SvgCustomNotesPaper } from '../icons/v2'; -import { type CSSProperties, styles, theme } from '../style'; +import { type CSSProperties, theme } from '../style'; import { Button } from './common/Button'; +import { Popover } from './common/Popover'; import { Tooltip } from './common/Tooltip'; import { View } from './common/View'; import { Notes } from './Notes'; @@ -81,7 +81,7 @@ export function NotesButton({ isOpen={isOpen} onOpenChange={onClose} placement={tooltipPosition} - style={{ ...styles.tooltip, marginTop: -8 }} + style={{ padding: 4 }} > diff --git a/packages/desktop-client/src/components/ThemeSelector.tsx b/packages/desktop-client/src/components/ThemeSelector.tsx index ed2a49508a..1127ec128b 100644 --- a/packages/desktop-client/src/components/ThemeSelector.tsx +++ b/packages/desktop-client/src/components/ThemeSelector.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useRef, useState } from 'react'; import type { Theme } from 'loot-core/src/types/prefs'; @@ -8,7 +8,7 @@ import { type CSSProperties, themeOptions, useTheme } from '../style'; import { Button } from './common/Button'; import { Menu } from './common/Menu'; -import { Tooltip } from './tooltips'; +import { Popover } from './common/Popover'; type ThemeSelectorProps = { style?: CSSProperties; @@ -17,6 +17,7 @@ type ThemeSelectorProps = { export function ThemeSelector({ style }: ThemeSelectorProps) { const [theme, switchTheme] = useTheme(); const [menuOpen, setMenuOpen] = useState(false); + const triggerRef = useRef(null); const { isNarrowWidth } = useResponsive(); @@ -34,26 +35,32 @@ export function ThemeSelector({ style }: ThemeSelectorProps) { const Icon = themeIcons[theme] || SvgSun; - return isNarrowWidth ? null : ( - + if (isNarrowWidth) { + return null; + } + + return ( + <> + + + setMenuOpen(false)} + > + ({ name, text }))} + /> + + ); } diff --git a/packages/desktop-client/src/components/Titlebar.tsx b/packages/desktop-client/src/components/Titlebar.tsx index 1d91cbc247..10d4ead371 100644 --- a/packages/desktop-client/src/components/Titlebar.tsx +++ b/packages/desktop-client/src/components/Titlebar.tsx @@ -35,6 +35,7 @@ import { MonthCountSelector } from './budget/MonthCountSelector'; import { Button, ButtonWithLoading } from './common/Button'; import { Link } from './common/Link'; import { Paragraph } from './common/Paragraph'; +import { Popover } from './common/Popover'; import { Text } from './common/Text'; import { View } from './common/View'; import { LoggedInUser } from './LoggedInUser'; @@ -42,7 +43,6 @@ import { useServerURL } from './ServerContext'; import { useSidebar } from './sidebar/SidebarProvider'; import { useSheetValue } from './spreadsheet/useSheetValue'; import { ThemeSelector } from './ThemeSelector'; -import { Tooltip } from './tooltips'; export const SWITCH_BUDGET_MESSAGE_TYPE = 'budget/switch-type'; @@ -290,7 +290,8 @@ function BudgetTitlebar() { const { sendEvent } = useContext(TitlebarContext); const [loading, setLoading] = useState(false); - const [showTooltip, setShowTooltip] = useState(false); + const [showPopover, setShowPopover] = useState(false); + const triggerRef = useRef(null); const reportBudgetEnabled = useFeatureFlag('reportBudget'); @@ -320,6 +321,7 @@ function BudgetTitlebar() { {reportBudgetEnabled && ( setShowTooltip(true)} + onClick={() => setShowPopover(true)} > {budgetType === 'report' ? 'Report budget' : 'Rollover budget'} - {showTooltip && ( - setShowTooltip(false)} - style={{ - padding: 10, - maxWidth: 400, - }} - > - - You are currently using a{' '} - - {budgetType === 'report' - ? 'Report budget' - : 'Rollover budget'} - . - {' '} - Switching will not lose any data and you can always switch back. - - - - Switch to a{' '} - {budgetType === 'report' - ? 'Rollover budget' - : 'Report budget'} - - - - - How do these types of budgeting work? - - - - )} + + setShowPopover(false)} + style={{ + padding: 10, + maxWidth: 400, + }} + > + + You are currently using a{' '} + + {budgetType === 'report' ? 'Report budget' : 'Rollover budget'}. + {' '} + Switching will not lose any data and you can always switch back. + + + + Switch to a{' '} + {budgetType === 'report' ? 'Rollover budget' : 'Report budget'} + + + + + How do these types of budgeting work? + + + )} diff --git a/packages/desktop-client/src/components/accounts/AccountSyncCheck.jsx b/packages/desktop-client/src/components/accounts/AccountSyncCheck.jsx index f253a51f16..6778992340 100644 --- a/packages/desktop-client/src/components/accounts/AccountSyncCheck.jsx +++ b/packages/desktop-client/src/components/accounts/AccountSyncCheck.jsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useRef, useState } from 'react'; import { useSelector } from 'react-redux'; import { useParams } from 'react-router-dom'; @@ -9,8 +9,8 @@ import { SvgExclamationOutline } from '../../icons/v1'; import { theme } from '../../style'; import { Button } from '../common/Button'; import { Link } from '../common/Link'; +import { Popover } from '../common/Popover'; import { View } from '../common/View'; -import { Tooltip } from '../tooltips'; function getErrorMessage(type, code) { switch (type.toUpperCase()) { @@ -56,6 +56,8 @@ export function AccountSyncCheck() { const { id } = useParams(); const [open, setOpen] = useState(false); + const triggerRef = useRef(null); + if (!failedAccounts) { return null; } @@ -85,6 +87,7 @@ export function AccountSyncCheck() { return ( - - - ) : ( - - )} - - - )} + + {showAuth ? ( + <> + + + + ) : ( + + )} + + ); } diff --git a/packages/desktop-client/src/components/common/Popover.tsx b/packages/desktop-client/src/components/common/Popover.tsx new file mode 100644 index 0000000000..94b029f745 --- /dev/null +++ b/packages/desktop-client/src/components/common/Popover.tsx @@ -0,0 +1,17 @@ +import { type ComponentProps } from 'react'; +import { Popover as ReactAriaPopover } from 'react-aria-components'; + +import { styles } from '../../style'; + +type PopoverProps = ComponentProps; + +export const Popover = ({ style = {}, ...props }: PopoverProps) => { + return ( + + ); +}; diff --git a/packages/desktop-client/src/components/sidebar/Sidebar.tsx b/packages/desktop-client/src/components/sidebar/Sidebar.tsx index bd6bc5335f..77e863ccf1 100644 --- a/packages/desktop-client/src/components/sidebar/Sidebar.tsx +++ b/packages/desktop-client/src/components/sidebar/Sidebar.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useRef, useState } from 'react'; import { useDispatch } from 'react-redux'; import { @@ -20,9 +20,9 @@ import { Button } from '../common/Button'; import { InitialFocus } from '../common/InitialFocus'; import { Input } from '../common/Input'; import { Menu } from '../common/Menu'; +import { Popover } from '../common/Popover'; import { Text } from '../common/Text'; import { View } from '../common/View'; -import { Tooltip } from '../tooltips'; import { Accounts } from './Accounts'; import { Item } from './Item'; @@ -145,6 +145,7 @@ function EditableBudgetName() { const [budgetName, setBudgetNamePref] = useLocalPref('budgetName'); const [editing, setEditing] = useState(false); const [menuOpen, setMenuOpen] = useState(false); + const triggerRef = useRef(null); function onMenuSelect(type: string) { setMenuOpen(false); @@ -195,9 +196,12 @@ function EditableBudgetName() { /> ); - } else { - return ( + } + + return ( + <> - ); - } + + setMenuOpen(false)} + > + + + + ); } diff --git a/upcoming-release-notes/2593.md b/upcoming-release-notes/2593.md new file mode 100644 index 0000000000..b94f89dfbf --- /dev/null +++ b/upcoming-release-notes/2593.md @@ -0,0 +1,6 @@ +--- +category: Maintenance +authors: [MatissJanis] +--- + +Migrating native `Tooltip` component to react-aria Tooltip/Popover (vol.2)