Skip to content
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

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

UnderKoen
Copy link
Member

@UnderKoen UnderKoen commented Nov 3, 2024

  • Make the context menu's postioned under the mouse instead of static.
  • Make the context menu non selectable.

#3706

fix: make popover non selectable
@actual-github-bot actual-github-bot bot changed the title enhance: context menu budget page positioning [WIP] enhance: context menu budget page positioning Nov 3, 2024
Copy link

netlify bot commented Nov 3, 2024

Deploy Preview for actualbudget ready!

Name Link
🔨 Latest commit 31d2983
🔍 Latest deploy log https://app.netlify.com/sites/actualbudget/deploys/6727ea2bf83aae000853c285
😎 Deploy Preview https://deploy-preview-3775.demo.actualbudget.org
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link
Contributor

github-actions bot commented Nov 3, 2024

Bundle Stats — desktop-client

Hey 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

Files count Total bundle size % Changed
10 5.34 MB → 5.34 MB (+2.25 kB) +0.04%
Changeset
File Δ Size
src/components/budget/envelope/budgetsummary/ToBudget.tsx 📈 +604 B (+18.07%) 3.26 kB → 3.85 kB
src/components/budget/SidebarCategory.tsx 📈 +431 B (+8.13%) 5.18 kB → 5.6 kB
src/components/budget/SidebarGroup.tsx 📈 +459 B (+7.65%) 5.86 kB → 6.31 kB
src/components/budget/envelope/EnvelopeBudgetComponents.tsx 📈 +780 B (+5.23%) 14.56 kB → 15.32 kB
src/components/common/Popover.tsx 📈 +26 B (+2.44%) 1.04 kB → 1.07 kB
View detailed bundle breakdown

Added

No assets were added

Removed

No assets were removed

Bigger

Asset File Size % Changed
static/js/index.js 3.34 MB → 3.35 MB (+1.38 kB) +0.04%
static/js/wide.js 238.83 kB → 239.69 kB (+890 B) +0.36%

Smaller

No assets were smaller

Unchanged

Asset File Size % Changed
static/js/workbox-window.prod.es5.js 5.69 kB 0%
static/js/resize-observer.js 18.37 kB 0%
static/js/indexeddb-main-thread-worker-e59fee74.js 13.5 kB 0%
static/js/BackgroundImage.js 122.29 kB 0%
static/js/AppliedFilters.js 21.3 kB 0%
static/js/usePreviewTransactions.js 1.64 kB 0%
static/js/narrow.js 82.57 kB 0%
static/js/ReportRouter.js 1.5 MB 0%

Copy link
Contributor

github-actions bot commented Nov 3, 2024

Bundle Stats — loot-core

Hey 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

Files count Total bundle size % Changed
1 1.27 MB 0%

Changeset

No files were changed

View detailed bundle breakdown

Added

No assets were added

Removed

No assets were removed

Bigger

No assets were bigger

Smaller

No assets were smaller

Unchanged

Asset File Size % Changed
kcab.worker.js 1.27 MB 0%

@UnderKoen UnderKoen changed the title [WIP] enhance: context menu budget page positioning enhance: context menu budget page positioning Nov 3, 2024
Copy link
Contributor

coderabbitai bot commented Nov 3, 2024

Walkthrough

The pull request introduces several modifications across multiple components in the desktop client application to enhance context menu functionality. In the SidebarCategory, SidebarGroup, EnvelopeBudgetComponents, and ToBudget components, new state variables crossOffset and offset are added to manage the positioning of context menus based on mouse events. These offsets are calculated in the onContextMenu event handlers and are utilized to ensure that the context menus appear correctly positioned when opened. The Popover components in these files are updated to accept the new offset properties, allowing for dynamic placement based on user interactions. Additionally, minor styling adjustments, such as adding margins, are made to improve the appearance of the popovers. The Popover component itself is modified to prevent text selection and includes logic to determine whether it should close when interacting outside of it. Overall, the changes focus on refining the user interface and improving the accuracy of context menu displays.

Possibly related PRs

  • Add context menu's #3381: This PR adds context menus to various components, which is directly related to the changes made in the main PR that enhance context menu functionality in the SidebarCategory, SidebarGroup, and other components.
  • Fix mobile balance modal colors #3492: This PR addresses the color display issue in the mobile balance modal, which is relevant as it may involve similar UI components and user interactions as those modified in the main PR.
  • Move help-related items under one single menu #3648: This PR proposes a new help menu structure that could potentially interact with the context menu functionality introduced in the main PR, enhancing overall user experience and accessibility.

Suggested labels

::sparkles: Merged


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?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 logic

While 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 positioning

While 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 handler

The 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 values

Consider 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 constant

The 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

📥 Commits

Reviewing files that changed from the base of the PR and between e078ed2 and 31d2983.

⛔ 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 and Overview.tsx show concurrent usage of multiple Popovers
  • Each Popover has its own independent state management through isOpen props
  • The pattern of using triggerRef with isOpen 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.

@youngcw
Copy link
Member

youngcw commented Nov 11, 2024

Could you give some example reproduction steps?

@UnderKoen
Copy link
Member Author

@youngcw
Sorry I hadn't change the description.

For reproduction of the selectable context menu. I don't know how @jfdoming achieved this #3381 (review)

@jfdoming
Copy link
Contributor

@youngcw Sorry I hadn't change the description.

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants