Skip to content

Commit

Permalink
enhance: context menu budget page positioning (#3775)
Browse files Browse the repository at this point in the history
* enhance: context menu budget page positioning
fix: make popover non selectable

* chore: release note

* Update upcoming-release-notes/3775.md

* chore: improve spelling

* feat: useContextMenu hook for context menus

* fix: linting
  • Loading branch information
UnderKoen authored Dec 9, 2024
1 parent a35af73 commit 5717d90
Show file tree
Hide file tree
Showing 11 changed files with 184 additions and 141 deletions.
22 changes: 11 additions & 11 deletions packages/desktop-client/src/components/budget/SidebarCategory.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// @ts-strict-ignore
import React, { type CSSProperties, type Ref, useRef, useState } from 'react';
import React, { type CSSProperties, type Ref, useRef } from 'react';
import { useTranslation } from 'react-i18next';

import {
type CategoryGroupEntity,
type CategoryEntity,
} from 'loot-core/src/types/models';

import { useFeatureFlag } from '../../hooks/useFeatureFlag';
import { useContextMenu } from '../../hooks/useContextMenu';
import { SvgCheveronDown } from '../../icons/v1';
import { theme } from '../../style';
import { Button } from '../common/Button2';
Expand Down Expand Up @@ -50,9 +50,9 @@ export function SidebarCategory({
const { t } = useTranslation();

const temporary = category.id === 'new';
const [menuOpen, setMenuOpen] = useState(false);
const { setMenuOpen, menuOpen, handleContextMenu, resetPosition, position } =
useContextMenu();
const triggerRef = useRef(null);
const contextMenusEnabled = useFeatureFlag('contextMenus');

const displayed = (
<View
Expand All @@ -66,11 +66,7 @@ export function SidebarCategory({
height: 20,
}}
ref={triggerRef}
onContextMenu={e => {
if (!contextMenusEnabled) return;
e.preventDefault();
setMenuOpen(true);
}}
onContextMenu={handleContextMenu}
>
<div
data-testid="category-name"
Expand All @@ -88,7 +84,10 @@ export function SidebarCategory({
variant="bare"
className="hover-visible"
style={{ color: 'currentColor', padding: 3 }}
onPress={() => setMenuOpen(true)}
onPress={() => {
resetPosition();
setMenuOpen(true);
}}
>
<SvgCheveronDown
width={14}
Expand All @@ -102,8 +101,9 @@ export function SidebarCategory({
placement="bottom start"
isOpen={menuOpen}
onOpenChange={() => setMenuOpen(false)}
style={{ width: 200 }}
style={{ width: 200, margin: 1 }}
isNonModal
{...position}
>
<Menu
onMenuSelect={type => {
Expand Down
21 changes: 11 additions & 10 deletions packages/desktop-client/src/components/budget/SidebarGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// @ts-strict-ignore
import React, { type CSSProperties, useRef, useState } from 'react';
import React, { type CSSProperties, useRef } from 'react';
import { type ConnectDragSource } from 'react-dnd';
import { useTranslation } from 'react-i18next';

import { useContextMenu } from '../../hooks/useContextMenu';
import { useFeatureFlag } from '../../hooks/useFeatureFlag';
import { SvgExpandArrow } from '../../icons/v0';
import { SvgCheveronDown } from '../../icons/v1';
Expand Down Expand Up @@ -58,9 +59,9 @@ export function SidebarGroup({
const isGoalTemplatesEnabled = useFeatureFlag('goalTemplatesEnabled');

const temporary = group.id === 'new';
const [menuOpen, setMenuOpen] = useState(false);
const { setMenuOpen, menuOpen, handleContextMenu, resetPosition, position } =
useContextMenu();
const triggerRef = useRef(null);
const contextMenusEnabled = useFeatureFlag('contextMenus');

const displayed = (
<View
Expand All @@ -75,11 +76,7 @@ export function SidebarGroup({
onClick={() => {
onToggleCollapse(group.id);
}}
onContextMenu={e => {
if (!contextMenusEnabled) return;
e.preventDefault();
setMenuOpen(true);
}}
onContextMenu={handleContextMenu}
>
{!dragPreview && (
<SvgExpandArrow
Expand Down Expand Up @@ -111,7 +108,10 @@ export function SidebarGroup({
<Button
variant="bare"
className="hover-visible"
onPress={() => setMenuOpen(true)}
onPress={() => {
resetPosition();
setMenuOpen(true);
}}
style={{ padding: 3 }}
>
<SvgCheveronDown width={14} height={14} />
Expand All @@ -122,8 +122,9 @@ export function SidebarGroup({
placement="bottom start"
isOpen={menuOpen}
onOpenChange={() => setMenuOpen(false)}
style={{ width: 200 }}
style={{ width: 200, margin: 1 }}
isNonModal
{...position}
>
<Menu
onMenuSelect={type => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import React, {
type CSSProperties,
memo,
useRef,
useState,
} from 'react';
import { useTranslation, Trans } from 'react-i18next';

Expand All @@ -14,7 +13,7 @@ import { evalArithmetic } from 'loot-core/src/shared/arithmetic';
import * as monthUtils from 'loot-core/src/shared/months';
import { integerToCurrency, amountToInteger } from 'loot-core/src/shared/util';

import { useFeatureFlag } from '../../../hooks/useFeatureFlag';
import { useContextMenu } from '../../../hooks/useContextMenu';
import { useUndo } from '../../../hooks/useUndo';
import { SvgCheveronDown } from '../../../icons/v1';
import { styles, theme } from '../../../style';
Expand Down Expand Up @@ -207,16 +206,27 @@ export const ExpenseCategoryMonth = memo(function ExpenseCategoryMonth({

const budgetMenuTriggerRef = useRef(null);
const balanceMenuTriggerRef = useRef(null);
const [budgetMenuOpen, setBudgetMenuOpen] = useState(false);
const [balanceMenuOpen, setBalanceMenuOpen] = useState(false);
const {
setMenuOpen: setBudgetMenuOpen,
menuOpen: budgetMenuOpen,
handleContextMenu: handleBudgetContextMenu,
resetPosition: resetBudgetPosition,
position: budgetPosition,
} = useContextMenu();
const {
setMenuOpen: setBalanceMenuOpen,
menuOpen: balanceMenuOpen,
handleContextMenu: handleBalanceContextMenu,
resetPosition: resetBalancePosition,
position: balancePosition,
} = useContextMenu();

const onMenuAction = (...args: Parameters<typeof onBudgetAction>) => {
onBudgetAction(...args);
setBudgetMenuOpen(false);
};

const { showUndoNotification } = useUndo();
const contextMenusEnabled = useFeatureFlag('contextMenus');

return (
<View
Expand All @@ -236,15 +246,14 @@ export const ExpenseCategoryMonth = memo(function ExpenseCategoryMonth({
}}
>
<View
ref={budgetMenuTriggerRef}
style={{
flex: 1,
flexDirection: 'row',
}}
onContextMenu={e => {
if (!contextMenusEnabled) return;
if (editing) return;
e.preventDefault();
setBudgetMenuOpen(true);
handleBudgetContextMenu(e);
}}
>
{!editing && (
Expand All @@ -261,9 +270,11 @@ export const ExpenseCategoryMonth = memo(function ExpenseCategoryMonth({
}}
>
<Button
ref={budgetMenuTriggerRef}
variant="bare"
onPress={() => setBudgetMenuOpen(true)}
onPress={() => {
resetBudgetPosition(2, -4);
setBudgetMenuOpen(true);
}}
style={{
padding: 3,
}}
Expand All @@ -278,11 +289,12 @@ export const ExpenseCategoryMonth = memo(function ExpenseCategoryMonth({

<Popover
triggerRef={budgetMenuTriggerRef}
placement="bottom start"
placement="bottom left"
isOpen={budgetMenuOpen}
onOpenChange={() => setBudgetMenuOpen(false)}
style={{ width: 200 }}
isNonModal
{...budgetPosition}
>
<BudgetMenu
onCopyLastMonthAverage={() => {
Expand Down Expand Up @@ -392,18 +404,25 @@ export const ExpenseCategoryMonth = memo(function ExpenseCategoryMonth({
</span>
</Field>
<Field
ref={balanceMenuTriggerRef}
name="balance"
width="flex"
style={{ paddingRight: styles.monthRightPadding, textAlign: 'right' }}
>
<span
ref={balanceMenuTriggerRef}
onClick={() => setBalanceMenuOpen(true)}
onContextMenu={e => {
if (!contextMenusEnabled) return;
e.preventDefault();
onClick={() => {
resetBalancePosition(-6, -4);
setBalanceMenuOpen(true);
}}
onContextMenu={e => {
handleBalanceContextMenu(e);
// We need to calculate differently from the hook ue to being aligned to the right
const rect = e.currentTarget.getBoundingClientRect();
resetBalancePosition(
e.clientX - rect.right + 200 - 8,
e.clientY - rect.bottom - 8,
);
}}
>
<BalanceWithCarryover
carryover={envelopeBudget.catCarryover(category.id)}
Expand All @@ -419,8 +438,9 @@ export const ExpenseCategoryMonth = memo(function ExpenseCategoryMonth({
placement="bottom end"
isOpen={balanceMenuOpen}
onOpenChange={() => setBalanceMenuOpen(false)}
style={{ width: 200 }}
style={{ width: 200, margin: 1 }}
isNonModal
{...balancePosition}
>
<BalanceMovementMenu
categoryId={category.id}
Expand Down
Loading

0 comments on commit 5717d90

Please sign in to comment.