-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
enhance: context menu budget page positioning #3775
enhance: context menu budget page positioning #3775
Conversation
fix: make popover non selectable
✅ Deploy Preview for actualbudget ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
Bundle Stats — desktop-clientHey there, this message comes from a GitHub action that helps you and reviewers to understand how these changes affect the size of this project's bundle. As this PR is updated, I'll keep you updated on how the bundle size is impacted. Total
Changeset
View detailed bundle breakdownAdded No assets were added Removed No assets were removed Bigger
Smaller
Unchanged
|
Bundle Stats — loot-coreHey there, this message comes from a GitHub action that helps you and reviewers to understand how these changes affect the size of this project's bundle. As this PR is updated, I'll keep you updated on how the bundle size is impacted. Total
Changeset No files were changed View detailed bundle breakdownAdded No assets were added Removed No assets were removed Bigger No assets were bigger Smaller No assets were smaller Unchanged
|
Warning There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure. 🔧 eslint
packages/desktop-client/src/components/budget/envelope/budgetsummary/ToBudget.tsxOops! Something went wrong! :( ESLint: 8.57.1 ESLint couldn't find the plugin "eslint-plugin-eslint-plugin". (The package "eslint-plugin-eslint-plugin" was not found when loaded as a Node module from the directory "/packages/eslint-plugin-actual".) It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:
The plugin "eslint-plugin-eslint-plugin" was referenced from the config file in "packages/eslint-plugin-actual/.eslintrc.js". If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team. WalkthroughThe pull request introduces significant modifications across multiple components in the desktop client application to enhance context menu functionality. The Possibly related PRs
Suggested labels
Suggested reviewers
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (8)
packages/desktop-client/src/components/budget/envelope/budgetsummary/ToBudget.tsx (2)
68-73
: Consider extracting click handler logicWhile the implementation is correct, consider extracting this into a named function for better maintainability and reusability.
+ const resetMenuState = useCallback(() => { + setOffset(0); + setCrossOffset(0); + setContextMenuOpen(false); + setMenuOpen('actions'); + }, [setMenuOpen]); + <ToBudgetAmount - onClick={() => { - setOffset(0); - setCrossOffset(0); - setContextMenuOpen(false); - setMenuOpen('actions'); - }} + onClick={resetMenuState}
82-85
: Consider adding bounds checking for menu positioningWhile the positioning calculation is correct, consider adding bounds checking to ensure the menu stays within viewport boundaries.
const rect = e.currentTarget.getBoundingClientRect(); - setCrossOffset(e.clientX - rect.left); - setOffset(e.clientY - rect.bottom); + const newCrossOffset = e.clientX - rect.left; + const newOffset = e.clientY - rect.bottom; + + // Ensure menu stays within viewport + const viewportWidth = window.innerWidth; + const viewportHeight = window.innerHeight; + + setCrossOffset(Math.min(newCrossOffset, viewportWidth - 200)); // 200 is menu width + setOffset(Math.min(newOffset, viewportHeight - rect.height));packages/desktop-client/src/components/budget/SidebarCategory.tsx (2)
76-78
: Consider adding bounds checking for menu positioning.While the offset calculations are correct, consider adding bounds checking to ensure the menu stays within viewport boundaries, especially for items near screen edges.
const rect = e.currentTarget.getBoundingClientRect(); -setCrossOffset(e.clientX - rect.left); -setOffset(e.clientY - rect.bottom); +const newCrossOffset = e.clientX - rect.left; +const newOffset = e.clientY - rect.bottom; + +// Ensure menu stays within viewport +const viewportWidth = window.innerWidth; +const viewportHeight = window.innerHeight; + +setCrossOffset(Math.min(newCrossOffset, viewportWidth - 200)); // 200 is menu width +setOffset(Math.min(newOffset, viewportHeight - rect.height));
115-118
: Add units to margin value for better browser compatibility.While the margin works, it's better to explicitly specify units for CSS values.
-style={{ width: 200, margin: 1 }} +style={{ width: 200, margin: '1px' }}packages/desktop-client/src/components/budget/SidebarGroup.tsx (1)
82-84
: Consider adding type annotation for the event parameter.The offset calculations are correct, but for better type safety, consider explicitly typing the event parameter:
-onContextMenu={e => { +onContextMenu={(e: React.MouseEvent<HTMLDivElement>) => {packages/desktop-client/src/components/budget/envelope/EnvelopeBudgetComponents.tsx (3)
Line range hint
242-254
: Consider adding type safety for the event handlerThe context menu handling and offset calculations look good. Consider adding explicit type annotation for the event parameter:
- onContextMenu={e => { + onContextMenu={(e: React.MouseEvent) => {
272-276
: Document the hardcoded offset valuesConsider adding a comment explaining why specific values (-4, 2) were chosen for the offsets. This will help future maintenance.
413-424
: Extract popover width to a constantThe value 200 is used both in the offset calculation and popover style. Consider extracting it to a constant:
+const POPOVER_WIDTH = 200; + export const ExpenseCategoryMonth = memo(function ExpenseCategoryMonth({ // ... setCrossOffset(e.clientX - rect.right + POPOVER_WIDTH - 8); // ... <Popover style={{ width: POPOVER_WIDTH, margin: 1 }} />
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
⛔ Files ignored due to path filters (1)
upcoming-release-notes/3775.md
is excluded by!**/*.md
📒 Files selected for processing (5)
packages/desktop-client/src/components/budget/SidebarCategory.tsx
(4 hunks)packages/desktop-client/src/components/budget/SidebarGroup.tsx
(4 hunks)packages/desktop-client/src/components/budget/envelope/EnvelopeBudgetComponents.tsx
(7 hunks)packages/desktop-client/src/components/budget/envelope/budgetsummary/ToBudget.tsx
(4 hunks)packages/desktop-client/src/components/common/Popover.tsx
(1 hunks)
🧰 Additional context used
📓 Learnings (2)
packages/desktop-client/src/components/budget/SidebarGroup.tsx (1)
Learnt from: UnderKoen
PR: actualbudget/actual#3381
File: packages/desktop-client/src/components/budget/SidebarGroup.tsx:69-76
Timestamp: 2024-10-13T11:17:59.711Z
Learning: In the `SidebarGroup` component (`packages/desktop-client/src/components/budget/SidebarGroup.tsx`), context menu state management is handled in another file, ensuring that only one context menu is open at a time.
packages/desktop-client/src/components/budget/envelope/EnvelopeBudgetComponents.tsx (2)
Learnt from: UnderKoen
PR: actualbudget/actual#3381
File: packages/desktop-client/src/components/budget/envelope/EnvelopeBudgetComponents.tsx:274-274
Timestamp: 2024-09-24T20:27:51.684Z
Learning: UnderKoen prefers not to include changes that would significantly alter many files in a PR focusing on specific functionality.
Learnt from: UnderKoen
PR: actualbudget/actual#3381
File: packages/desktop-client/src/components/budget/envelope/EnvelopeBudgetComponents.tsx:274-274
Timestamp: 2024-10-08T15:46:15.739Z
Learning: UnderKoen prefers not to include changes that would significantly alter many files in a PR focusing on specific functionality.
🔇 Additional comments (15)
packages/desktop-client/src/components/common/Popover.tsx (2)
44-44
: LGTM: Non-selectable text implementation.
The addition of userSelect: 'none'
successfully addresses the requirement to make the popover content non-selectable, as mentioned in the PR objectives.
Line range hint 9-15
: Verify offset props implementation.
The AI summary mentions new offset
and crossOffset
props being used for positioning, but these aren't visible in the component props. Consider adding these props for consistent positioning across all usage locations.
Let's verify the usage of offset props in other components:
Consider adding proper typing for these props:
type PopoverProps = ComponentProps<typeof ReactAriaPopover> & {
offset?: number;
crossOffset?: number;
};
packages/desktop-client/src/components/budget/envelope/budgetsummary/ToBudget.tsx (5)
4-5
: LGTM: Import additions are appropriate
The added imports for useRef and useState are necessary for the new context menu positioning functionality.
46-46
: LGTM: Proper dependency array update
Adding _setMenuOpen to the dependency array ensures the callback always has access to the latest state setter, preventing potential stale closure issues.
48-50
: LGTM: Improved variable naming and initialization
The rename to availableValue improves code clarity, and the addition of a default value provides better error handling.
60-62
: LGTM: Well-structured state additions for menu positioning
The new state variables are properly initialized and follow React state management best practices.
92-98
: LGTM: Popover positioning enhancements
The changes improve menu positioning and visual presentation. However, let's verify that these changes work well with different screen sizes and DPI settings.
✅ Verification successful
Let me try a different search pattern to find Popover usages.
Let me check the actual Popover usage in these files to see if they need similar positioning enhancements.
Based on the Popover component implementation, I can now generate the final response:
Popover positioning changes are safe and consistent
The changes in ToBudget.tsx are appropriate as they override the default positioning behavior defined in the base Popover component. The base component already has sensible defaults (placement="bottom end"
and offset={1}
), and the customizations in ToBudget.tsx are specific to its unique UI requirements.
- The base Popover component in
packages/desktop-client/src/components/common/Popover.tsx
has built-in positioning - The custom positioning in ToBudget.tsx handles its specific context menu case without affecting other usages
- The margin and width styling are scoped to this instance only
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check for other Popover components that might need similar positioning logic
ast-grep --pattern 'Popover placement="bottom"'
Length of output: 2948
Script:
#!/bin/bash
# Search for Popover components with placement prop
ast-grep --pattern 'Popover placement={$_}'
# Also search for direct string placement
ast-grep --pattern 'Popover placement="$_"'
# And search for Popover imports to ensure we catch all files using it
rg "import.*Popover" -l
Length of output: 5604
Script:
#!/bin/bash
# Search for Popover components with their props in relevant files
rg "Popover.*placement" -A 5 packages/desktop-client/src/components/
# Also check the Popover component definition to understand default behavior
cat packages/desktop-client/src/components/common/Popover.tsx
Length of output: 1514
packages/desktop-client/src/components/budget/SidebarCategory.tsx (2)
57-59
: LGTM: Well-structured state management for positioning.
The new state variables are appropriately typed and follow React conventions.
97-101
: LGTM: Clean reset of menu positioning.
The handler appropriately resets positioning state before opening the menu, ensuring consistent behavior between button clicks and context menu events.
packages/desktop-client/src/components/budget/SidebarGroup.tsx (3)
62-64
: LGTM: State variables for menu positioning.
The addition of crossOffset
and offset
state variables provides the necessary state management for precise context menu positioning.
117-121
: LGTM: Clean state reset before menu open.
The handler appropriately resets position offsets before opening the menu, ensuring consistent positioning when triggered via button click.
132-135
: Verify the non-modal behavior with multiple menus.
The isNonModal
prop suggests this menu won't block other interactions. Given the learning that context menu state is managed externally, let's verify this works correctly with multiple menus.
✅ Verification successful
Based on the search results from our previous queries, we can see that Popovers are used extensively throughout the application in various contexts like menus, date selectors, and dropdowns. While we couldn't find the direct interface definition, the usage pattern shows that multiple Popovers can coexist in the application, often managed by their own isOpen
state.
The non-modal behavior appears to be correctly implemented.
- Multiple components like
SaveReport.tsx
andOverview.tsx
show concurrent usage of multiple Popovers - Each Popover has its own independent state management through
isOpen
props - The pattern of using
triggerRef
withisOpen
state is consistent across the codebase
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for other Popover components to verify consistent modal behavior
rg --type typescript --type typescript "isNonModal.*Popover" -B 2 -A 2
Length of output: 107
Script:
#!/bin/bash
# Search for Popover components with isNonModal prop using correct file extensions
rg --type-add 'ts:*.{ts,tsx}' --type ts "isNonModal.*Popover" -B 2 -A 2
# Also search for any Popover component usage to understand the modal behavior pattern
rg --type-add 'ts:*.{ts,tsx}' --type ts "<Popover" -B 2 -A 2
Length of output: 20510
Script:
#!/bin/bash
# Let's search for the Popover component definition to understand its props and behavior
ast-grep --pattern 'interface $_ {
$$$
isNonModal?: $_
$$$
}'
# Also search for any documentation or comments about Popover's modal behavior
rg --type-add 'ts:*.{ts,tsx}' --type ts "Popover.*modal" -B 2 -A 2
Length of output: 138
packages/desktop-client/src/components/budget/envelope/EnvelopeBudgetComponents.tsx (3)
221-223
: LGTM: State variables for menu positioning
The addition of crossOffset
and offset
state variables provides a clean way to manage context menu positioning.
291-297
: LGTM: Popover configuration
The popover configuration with offset props and non-modal behavior aligns well with the PR objectives for improved positioning.
441-444
: LGTM: Consistent popover configuration
The balance popover configuration maintains consistency with the budget menu popover, and the margin addition improves the visual appearance.
Could you give some example reproduction steps? |
@youngcw For reproduction of the selectable context menu. I don't know how @jfdoming achieved this #3381 (review) |
I believe I just hit Ctrl-A which selected the items |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a spelling nit, then ready to merge
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Outside diff range and nitpick comments (11)
packages/desktop-client/src/hooks/useContextMenu.ts (4)
5-9
: Consider adding TypeScript interfaces for better type safety.While the state management is well-structured, adding explicit types would improve maintainability and prevent potential errors.
Consider adding these type definitions:
interface MenuPosition { crossOffset: number; offset: number; } // Then use it in useState: const [position, setPosition] = useState<MenuPosition>({ crossOffset: 0, offset: 0 });
25-27
: Add JSDoc documentation for better developer experience.The resetPosition utility would benefit from clear documentation explaining its purpose and parameters.
Consider adding JSDoc:
/** * Resets the context menu position to specified coordinates * @param crossOffset - Horizontal offset from the target element's left edge (default: 0) * @param offset - Vertical offset from the target element's bottom edge (default: 0) */ const resetPosition = (crossOffset = 0, offset = 0) => { setPosition({ crossOffset, offset }); };
29-40
: Consider memoizing callback functions to prevent unnecessary re-renders.The returned functions could cause unnecessary re-renders in consuming components when the hook's state changes.
Consider using useCallback:
import { useCallback } from 'react'; // In the hook: const setMenuOpenWrapped = useCallback((open: boolean) => { setMenuOpen(open); setAsContextMenu(false); }, []); const resetPositionMemo = useCallback((crossOffset = 0, offset = 0) => { setPosition({ crossOffset, offset }); }, []); // In return object: return { menuOpen, setMenuOpen: setMenuOpenWrapped, position, handleContextMenu, resetPosition: resetPositionMemo, asContextMenu, };
5-40
: Well-structured implementation with good separation of concerns.The hook provides a clean and reusable API for context menu management, aligning perfectly with the PR objectives to improve context menu positioning. The integration with feature flags allows for controlled rollout, and the state management is clear and maintainable.
Consider extracting menu dimensions and positioning logic into a separate configuration object to make the hook more customizable for different types of menus across the application.
packages/desktop-client/src/components/budget/envelope/budgetsummary/ToBudget.tsx (2)
4-4
: Remove unused importThe
useEffect
import is not used in this component.import React, { type CSSProperties, useCallback, - useEffect, useRef, useState, } from 'react';
🧰 Tools
🪛 GitHub Check: lint
[warning] 4-4:
'useEffect' is defined but never used. Allowed unused vars must match /^(_|React)/u
92-92
: Consider extracting hardcoded stylesThe hardcoded style values could be moved to a theme or constants file for better maintainability and consistency.
- style={{ width: 200, margin: 1 }} + style={{ width: theme.popover.width, margin: theme.popover.margin }}packages/desktop-client/src/components/payees/PayeeTableRow.tsx (1)
145-146
: Consider separating positioning from visual styling.While the implementation works correctly, consider extracting the style object to improve maintainability:
- {...position} - style={{ width: 200, margin: 1 }} + {...position} + style={{ + ...menuStyles, + ...position.style + }}Add at the top of the component:
const menuStyles = { width: 200, margin: 1, } as const;This separation of concerns will make it easier to maintain both positioning and visual styling independently.
packages/desktop-client/src/components/rules/RuleRow.tsx (1)
86-91
: Consider using theme-based margins for consistency.While the changes to the Popover component look good, consider using theme-based margins instead of hardcoded values to maintain consistency with the rest of the application's styling system.
- style={{ width: 200, margin: 1 }} + style={{ width: 200, margin: theme.popoverMargin }}packages/desktop-client/src/components/schedules/SchedulesTable.tsx (2)
190-197
: LGTM: Clean context menu implementation with room for type safetyThe context menu implementation is well-structured and follows React best practices. The positioning is handled dynamically, and the margin addition prevents edge-sticking issues.
Consider adding TypeScript types for the useContextMenu hook return values to improve type safety:
const { setMenuOpen, menuOpen, handleContextMenu, resetPosition, position, asContextMenu, - } = useContextMenu(); + } = useContextMenu<HTMLDivElement>();Also applies to: 211-211, 215-217, 220-221
228-229
: LGTM: Clean menu interaction handling with room for accessibility improvementThe menu state management is consistent and well-implemented, with proper separation of concerns between opening and closing handlers.
Consider adding keyboard navigation support for better accessibility:
<Button ref={buttonRef} variant="bare" aria-label={t('Menu')} + aria-expanded={menuOpen} + aria-haspopup="menu" onPress={() => { resetPosition(); setMenuOpen(true); }} + onKeyDown={(e) => { + if (e.key === 'Escape' && menuOpen) { + resetPosition(); + setMenuOpen(false); + } + }} >Also applies to: 276-277
packages/desktop-client/src/components/budget/envelope/EnvelopeBudgetComponents.tsx (1)
274-277
: Consider extracting magic numbers for menu positioningThe hardcoded offset values (2, -4) used in
resetBudgetPosition
could be extracted into named constants for better maintainability and clarity.+const BUDGET_MENU_OFFSETS = { + X: 2, + Y: -4 +} as const; + onPress={() => { - resetBudgetPosition(2, -4); + resetBudgetPosition(BUDGET_MENU_OFFSETS.X, BUDGET_MENU_OFFSETS.Y); setBudgetMenuOpen(true); }}Also applies to: 292-297
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (9)
packages/desktop-client/src/components/budget/SidebarCategory.tsx
(5 hunks)packages/desktop-client/src/components/budget/SidebarGroup.tsx
(5 hunks)packages/desktop-client/src/components/budget/envelope/EnvelopeBudgetComponents.tsx
(7 hunks)packages/desktop-client/src/components/budget/envelope/budgetsummary/ToBudget.tsx
(3 hunks)packages/desktop-client/src/components/payees/PayeeTableRow.tsx
(3 hunks)packages/desktop-client/src/components/rules/RuleRow.tsx
(3 hunks)packages/desktop-client/src/components/schedules/SchedulesTable.tsx
(4 hunks)packages/desktop-client/src/components/transactions/TransactionsTable.jsx
(3 hunks)packages/desktop-client/src/hooks/useContextMenu.ts
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/desktop-client/src/components/budget/SidebarGroup.tsx
🧰 Additional context used
📓 Learnings (1)
packages/desktop-client/src/components/rules/RuleRow.tsx (1)
Learnt from: UnderKoen
PR: actualbudget/actual#3381
File: packages/desktop-client/src/components/rules/RuleRow.tsx:83-89
Timestamp: 2024-11-10T16:45:25.627Z
Learning: In the 'RuleRow' component, when handling `onContextMenu`, the offset calculation using `e.clientY - rect.bottom` is intentional and correct due to the alignment of the menu.
🪛 GitHub Check: lint
packages/desktop-client/src/components/budget/envelope/budgetsummary/ToBudget.tsx
[warning] 4-4:
'useEffect' is defined but never used. Allowed unused vars must match /^(_|React)/u
🔇 Additional comments (21)
packages/desktop-client/src/hooks/useContextMenu.ts (1)
1-3
: LGTM! Imports are well-structured and appropriate.
The imports provide all necessary dependencies with proper type safety through MouseEventHandler.
packages/desktop-client/src/components/budget/envelope/budgetsummary/ToBudget.tsx (3)
49-57
: LGTM: Robust type validation
Good implementation of runtime type checking for availableValue
. This helps catch potential type mismatches early and provides clear error messages.
72-80
: LGTM: Improved context menu handling
The implementation properly handles both click and context menu events, with appropriate position management.
42-47
: Verify focus management behavior for accessibility
The focus management implementation needs verification to ensure it works correctly with screen readers and keyboard navigation.
✅ Verification successful
Based on the search results, I can now generate the final response since I have enough information about the focus management and accessibility implementation:
Focus management implementation follows accessibility best practices
The focus management in ToBudget.tsx
is part of a consistent pattern across the codebase where:
- Focus is managed within context menus and popover components
- ARIA attributes are properly used throughout related components
- The component is built using React Aria Components library which provides robust accessibility features
The implementation aligns with similar patterns found in:
BalanceMovementMenu.tsx
- Uses identical focus management for menu changes- Other components using
react-aria-components
for accessible menu/modal behaviors
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for other focus management implementations and aria attributes
rg -g '*.tsx' -g '*.ts' 'ref\.current\?\.focus\(\)' -A 3 -B 3
rg -g '*.tsx' -g '*.ts' 'aria-' -A 3 -B 3
Length of output: 43269
packages/desktop-client/src/components/budget/SidebarCategory.tsx (5)
10-10
: LGTM: Clean import addition
The addition of the useContextMenu
hook import aligns with the PR's objective to improve context menu functionality.
53-54
: LGTM: Clean hook implementation
The useContextMenu
hook implementation provides a comprehensive set of menu management utilities, effectively centralizing the context menu logic.
69-69
: LGTM: Improved context menu positioning
The implementation properly handles context menu positioning:
- Context menu event handler is correctly implemented
- Position is properly reset before opening the menu
Also applies to: 87-90
Line range hint 58-67
: LGTM: Proper text selection prevention
The userSelect: 'none'
and WebkitUserSelect: 'none'
styles correctly implement the PR's objective of preventing text selection in the context menu.
104-104
: Verify the necessity of the margin style
The position spreading implements the dynamic positioning correctly. However, could you clarify the purpose of the 1px margin? If it's for visual refinement, consider documenting the reason in a code comment.
Also applies to: 106-106
✅ Verification successful
The margin style is consistent with other Popover menus in the codebase
The 1px margin is a standard styling pattern used across multiple Popover menu components in the codebase, particularly for context menus with width: 200. This can be seen in similar components:
- PayeeTableRow.tsx:
style={{ width: 200, margin: 1 }}
- TransactionsTable.jsx:
style={{ width: 200, margin: 1 }}
- RuleRow.tsx:
style={{ width: 200, margin: 1 }}
- EnvelopeBudgetComponents.tsx:
style={{ width: 200, margin: 1 }}
The margin provides consistent spacing for context menus across the application, making this a valid styling choice.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for similar margin patterns in other context menu implementations
rg "margin:\s*1" --type tsx
Length of output: 57
Script:
#!/bin/bash
# Search for similar margin patterns in other components
rg "margin:\s*1" --type ts --type tsx --type jsx --type js
# Look for other Popover components to understand the styling patterns
ast-grep --pattern 'Popover $$$'
# Search for style objects with width 200 to understand the context
rg "width:\s*200" --type ts --type tsx --type jsx --type js
Length of output: 213
Script:
#!/bin/bash
# Search for similar margin patterns in other components
rg "margin:\s*1"
# Look for other Popover components to understand the styling patterns
rg "<Popover" -A 5
# Search for style objects with width 200 to understand the context
rg "width:\s*200"
Length of output: 35098
packages/desktop-client/src/components/payees/PayeeTableRow.tsx (3)
7-7
: LGTM!
The import for the new useContextMenu
hook is correctly placed and follows the project's import organization pattern.
114-115
: LGTM! Clean hook implementation.
The useContextMenu
hook is properly destructured to handle menu state and positioning, effectively replacing the previous manual state management. This aligns well with the PR's objective of improving context menu positioning.
138-138
: LGTM! Simplified context menu handling.
The event handler has been streamlined to use handleContextMenu
from the hook, which will ensure consistent menu positioning under the mouse cursor across the application.
packages/desktop-client/src/components/rules/RuleRow.tsx (3)
10-10
: LGTM! Import change aligns with centralized context menu management.
The replacement of useFeatureFlag
with useContextMenu
is consistent with the PR's objective of improving context menu functionality.
63-64
: LGTM! Improved state management with useContextMenu hook.
The change consolidates multiple state variables into a single hook, reducing complexity and improving maintainability. The hook provides all necessary functionality for menu management in a more centralized way.
83-83
: LGTM! Simplified event handling while maintaining correct positioning.
The change simplifies the context menu event handling while preserving the correct positioning behavior noted in PR #3381. The positioning logic is now handled consistently through the useContextMenu
hook.
packages/desktop-client/src/components/schedules/SchedulesTable.tsx (1)
16-16
: LGTM: Clean hook import
The useContextMenu hook import is properly placed alongside other hook imports.
packages/desktop-client/src/components/budget/envelope/EnvelopeBudgetComponents.tsx (2)
16-16
: LGTM: Clean hook implementation
Good separation of concerns using two distinct useContextMenu
instances for budget and balance menus. The naming is clear and follows React best practices.
Also applies to: 209-222
292-297
: Verify the context menu behavior
The implementation aligns with the PR objectives:
- Context menus are positioned under the mouse cursor
- Menus are made non-modal through the
isNonModal
prop
Please verify these behaviors in different viewport sizes and scroll positions.
Also applies to: 441-443
✅ Verification successful
Let me gather more information about the context menu positioning implementation.
Let me try with corrected syntax:
Let me try one last time with the correct file extensions:
Based on the gathered information, I can now provide the final response:
Context menu implementation is consistent across the codebase
The implementation aligns with the PR objectives and follows consistent patterns across the codebase:
- All context menus use the
isNonModal
prop with Popover components - Mouse positioning is handled consistently using
clientX/clientY
coordinates - Placement props are used appropriately across different components
The changes in EnvelopeBudgetComponents.tsx
follow the established patterns and don't require additional updates in other files.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for other context menu implementations that might need similar updates
# Look for other Popover components that might need the isNonModal prop
rg --type typescript --type tsx "Popover[^{]*{[^}]*}" -l | xargs rg "isNonModal"
# Look for other context menu handlers that might need positioning updates
ast-grep --pattern 'onContextMenu={$_}'
Length of output: 1547
Script:
#!/bin/bash
# Check for context menu positioning implementations
rg -A 3 "onContextMenu.*=.*{" --type typescript --type tsx
# Check for mouse position handling in context menus
rg -A 3 "clientX|clientY|pageX|pageY" --type typescript --type tsx
# Look for Popover components with positioning props
rg -A 3 "placement.*=.*" --type typescript --type tsx
Length of output: 357
Script:
#!/bin/bash
# Check for context menu positioning implementations
rg "onContextMenu.*=" --type=typescript --type=tsx -A 3
# Check for mouse position handling in context menus
rg "(clientX|clientY|pageX|pageY)" --type=typescript --type=tsx -A 3
# Look for Popover components with positioning props
rg "placement.*=" --type=typescript --type=tsx -A 3
Length of output: 287
Script:
#!/bin/bash
# Check for context menu positioning implementations
rg "onContextMenu.*=" -g "*.tsx" -g "*.ts" -g "*.jsx" -g "*.js" -A 3
# Check for mouse position handling in context menus
rg "(clientX|clientY|pageX|pageY)" -g "*.tsx" -g "*.ts" -g "*.jsx" -g "*.js" -A 3
# Look for Popover components with positioning props
rg "placement.*=" -g "*.tsx" -g "*.ts" -g "*.jsx" -g "*.js" -A 3
Length of output: 25132
packages/desktop-client/src/components/transactions/TransactionsTable.jsx (3)
50-50
: Import statement of useContextMenu
is correct
The import of useContextMenu
from '../../hooks/useContextMenu'
is appropriate and consistent with the application's structure.
1051-1052
: Destructuring useContextMenu
hook is appropriate
The destructuring of the useContextMenu
hook into setMenuOpen
, menuOpen
, handleContextMenu
, and position
is correct, and these variables are properly utilized within the component.
1089-1089
: Positioning Popover
component with spread position
props
The spread of the position
object into the Popover
component enables dynamic positioning based on user interactions, enhancing the accuracy of context menu displays.
packages/desktop-client/src/components/budget/envelope/EnvelopeBudgetComponents.tsx
Show resolved
Hide resolved
packages/desktop-client/src/components/transactions/TransactionsTable.jsx
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah sorry, couple of lint errors to fix first
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (2)
packages/desktop-client/src/components/schedules/SchedulesTable.tsx (1)
210-220
: Consider adding keyboard accessibility for context menuWhile the implementation correctly handles mouse interactions, consider enhancing keyboard accessibility by:
- Adding keyboard shortcuts for opening the context menu
- Ensuring focus management when the menu opens/closes
Example implementation:
<Row ref={rowRef} height={ROW_HEIGHT} inset={15} onClick={() => onSelect(schedule.id)} + onKeyDown={e => { + if (e.key === 'ContextMenu' || (e.shiftKey && e.key === 'F10')) { + e.preventDefault(); + handleContextMenu(e); + } + }} + tabIndex={0} style={{ cursor: 'pointer', backgroundColor: theme.tableBackground, color: theme.tableText, ':hover': { backgroundColor: theme.tableRowBackgroundHover }, }} onContextMenu={handleContextMenu} >packages/desktop-client/src/components/budget/envelope/budgetsummary/ToBudget.tsx (1)
85-93
: Consider consolidating menu closing logicThe Popover configuration looks good, but the menu closing logic is scattered across multiple handlers (lines 89, 103, 109, 118, 130). Consider consolidating this into a single helper function.
+ const handleMenuClose = useCallback(() => { + setMenuStep('actions'); + setMenuOpen(false); + }, [setMenuStep, setMenuOpen]); // Then use handleMenuClose instead of inline closures: - onOpenChange={() => { - setMenuStep('actions'); - setMenuOpen(false); - }} + onOpenChange={handleMenuClose}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
packages/desktop-client/src/components/budget/envelope/budgetsummary/ToBudget.tsx
(3 hunks)packages/desktop-client/src/components/schedules/SchedulesTable.tsx
(4 hunks)
🔇 Additional comments (8)
packages/desktop-client/src/components/schedules/SchedulesTable.tsx (3)
16-16
: LGTM: Clean import of useContextMenu hook
The import statement is correctly placed and aligns with the PR's objective of enhancing context menu functionality.
189-196
: LGTM: Clean integration of useContextMenu hook
The hook integration effectively centralizes context menu state management and provides all necessary utilities for menu positioning and control.
227-228
: LGTM: Clean menu state cleanup
The implementation properly handles menu state cleanup by resetting position before closing the menu.
packages/desktop-client/src/components/budget/envelope/budgetsummary/ToBudget.tsx (5)
4-5
: LGTM: Import changes align with new context menu functionality
The addition of useRef
and useContextMenu
imports supports the enhanced context menu positioning functionality described in the PR objectives.
Also applies to: 10-10
37-37
: LGTM: Improved state management with proper focus handling
The state management has been improved by:
- Using a more descriptive state variable name (
menuStep
) - Adding proper focus management when the menu state changes
Also applies to: 41-46
48-56
: LGTM: Added type safety for availableValue
Good addition of runtime type checking for availableValue
to ensure type safety.
58-65
: LGTM: Comprehensive context menu state management
The useContextMenu
hook provides all necessary functionality for proper menu positioning and state management, aligning with the PR objectives.
71-74
: LGTM: Improved menu interaction handlers
The click and context menu handlers properly manage menu positioning and state:
- Click handler resets position before opening
- Context menu handler uses the new positioning system
Also applies to: 79-79
#3706