Skip to content

fix: Improperly aligned unfolding sub-items in context menu in data browser #2726

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

Merged
merged 19 commits into from
May 24, 2025

Conversation

dblythy
Copy link
Member

@dblythy dblythy commented Apr 7, 2025

New Pull Request Checklist

Issue Description

Closes: #2635

Approach

TODOs before merging

  • Add tests
  • Add changes to documentation (guides, repository pages, in-code descriptions)

Summary by CodeRabbit

  • New Features

    • Improved submenu positioning to better fit within the visible screen area, ensuring menus do not overflow the viewport.
    • Enhanced submenu navigation for more consistent visibility when hovering over menu items.
    • Unified hover behavior for all menu items to streamline submenu access.
    • Enhanced handling and styling of disabled menu items for clearer user feedback.
  • Bug Fixes

    • Addressed issues with submenu alignment and offset, resulting in more accurate menu placement.
    • Improved event handling to prevent unintended menu interactions.

Copy link

parse-github-assistant bot commented Apr 7, 2025

🚀 Thanks for opening this pull request! We appreciate your effort in improving the project. Please let us know once your pull request is ready for review.

@dblythy dblythy changed the title Update ContextMenu.react.js fix: context menu position Apr 7, 2025
Copy link

I will reformat the title to use the proper commit message syntax.

@parse-github-assistant parse-github-assistant bot changed the title fix: context menu position fix: Context menu position Apr 7, 2025
Copy link

uffizzi-cloud bot commented Apr 7, 2025

Uffizzi Ephemeral Environment deployment-62506

⌚ Updated Apr 07, 2025, 12:11 UTC

☁️ https://app.uffizzi.com/github.com/parse-community/parse-dashboard/pull/2726

📄 View Application Logs etc.

What is Uffizzi? Learn more

@mtrezza
Copy link
Member

mtrezza commented Apr 7, 2025

I tried out all the positions to see which ones work. It's painful that we have to spend time on fixing something that should work OOTB. I hope we get to #2460 soon.

OK

top-right short: OK

image

top-right long: OK

image

bottom-right long: OK

image

bottom-left long: OK

image

top-left short: OK

image

top-left long: OK

image

NOK

bottom-right short: NOK - subitem should align with top border; I guess the logic could be, if the count of sub-items <= count of main items, then align with the top border, as we know there is enough space towards the bottom.

image

bottom-left short: NOK

image

@mtrezza mtrezza changed the title fix: Context menu position fix: Improperly aligned unfolding sub-items in context menu in data browser Apr 7, 2025
@dblythy dblythy requested a review from a team April 9, 2025 10:51
@mtrezza mtrezza closed this Apr 10, 2025
@mtrezza mtrezza reopened this Apr 10, 2025
@mtrezza mtrezza closed this Apr 10, 2025
@mtrezza mtrezza reopened this Apr 10, 2025
Copy link

uffizzi-cloud bot commented Apr 10, 2025

Uffizzi Ephemeral Environment deployment-62642

⌚ Updated Apr 10, 2025, 01:15 UTC

☁️ https://app.uffizzi.com/github.com/parse-community/parse-dashboard/pull/2726

📄 View Application Logs etc.

What is Uffizzi? Learn more

Copy link
Member

@mtrezza mtrezza left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dashboard crashes when opening session with uffizzi link

@mtrezza
Copy link
Member

mtrezza commented Apr 10, 2025

The issue seems to be a different one; I've opened #2743 with high priority, as it's currently blocking the other PRs.

@mtrezza mtrezza closed this Apr 13, 2025
@mtrezza mtrezza reopened this Apr 13, 2025
Copy link

uffizzi-cloud bot commented Apr 13, 2025

Uffizzi Ephemeral Environment deployment-62729

⌚ Updated Apr 13, 2025, 14:24 UTC

☁️ https://app.uffizzi.com/github.com/parse-community/parse-dashboard/pull/2726

📄 View Application Logs etc.

What is Uffizzi? Learn more

Copy link
Member

@mtrezza mtrezza left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sub-menu is always shown, even if the mouse is not over its parent item. In the screenshot below the mouse was hovering over "Edit row":

image

@parseplatformorg
Copy link
Contributor

parseplatformorg commented Apr 25, 2025

🎉 Snyk checks have passed. No issues have been found so far.

security/snyk check is complete. No issues have been found. (View Details)

@dblythy dblythy requested a review from a team April 26, 2025 09:47
coderabbitai[bot]
coderabbitai bot previously approved these changes May 18, 2025
@mtrezza mtrezza closed this May 19, 2025
@mtrezza mtrezza reopened this May 19, 2025
Copy link

uffizzi-cloud bot commented May 19, 2025

Uffizzi Ephemeral Environment deployment-63764

⌚ Updated May 19, 2025, 11:50 UTC

☁️ https://app.uffizzi.com/github.com/parse-community/parse-dashboard/pull/2726

📄 View Application Logs etc.

What is Uffizzi? Learn more

Copy link
Member

@mtrezza mtrezza left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are issues in the bottom left and right corners:

Screen.Recording.2025-05-19.at.14.11.23.mov

Copy link

@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: 2

🔭 Outside diff range comments (1)
src/components/ContextMenu/ContextMenu.react.js (1)

115-139: ⚠️ Potential issue

Better ref management and event handler organization

Moving the menuRef to component level and organizing the click handler inside the effect hook improves code organization and maintainability.

-  if (!visible) return null;
+  if (!visible) { return null; }

Consider adding a cleanup of event listeners when the menu hides:

  const hide = () => {
    setVisible(false);
    setPath([0]);
+   // When we hide the menu, ensure listeners are properly cleaned up
+   document.removeEventListener('mousedown', handleClickOutside);
  };

  useEffect(() => {
    const handleClickOutside = event => {
      if (menuRef.current && !menuRef.current.contains(event.target)) {
        hide();
      }
    };
    document.addEventListener('mousedown', handleClickOutside);
    return () => {
      document.removeEventListener('mousedown', handleClickOutside);
    };
-  }, []);
+  }, [visible]); // Re-add listener when visibility changes
🧹 Nitpick comments (1)
src/components/ContextMenu/ContextMenu.react.js (1)

76-81: Fix style indentation

The style object has inconsistent indentation.

  const style = position
    ? {
-        transform: `translate(${position.x}px, ${position.y}px)`,
-        maxHeight: '80vh',
-        overflowY: 'auto',
-        opacity: 1,
-        position: 'absolute',
+      transform: `translate(${position.x}px, ${position.y}px)`,
+      maxHeight: '80vh',
+      overflowY: 'auto',
+      opacity: 1,
+      position: 'absolute',
      }
    : {};
🧰 Tools
🪛 GitHub Check: Lint

[failure] 81-81:
Expected indentation of 4 spaces but found 6


[failure] 80-80:
Expected indentation of 6 spaces but found 8


[failure] 79-79:
Expected indentation of 6 spaces but found 8


[failure] 78-78:
Expected indentation of 6 spaces but found 8


[failure] 77-77:
Expected indentation of 6 spaces but found 8


[failure] 76-76:
Expected indentation of 6 spaces but found 8

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 40cde80 and ebc6e1c.

📒 Files selected for processing (1)
  • src/components/ContextMenu/ContextMenu.react.js (5 hunks)
🧰 Additional context used
🪛 GitHub Check: Lint
src/components/ContextMenu/ContextMenu.react.js

[failure] 81-81:
Expected indentation of 4 spaces but found 6


[failure] 80-80:
Expected indentation of 6 spaces but found 8


[failure] 79-79:
Expected indentation of 6 spaces but found 8


[failure] 78-78:
Expected indentation of 6 spaces but found 8


[failure] 77-77:
Expected indentation of 6 spaces but found 8


[failure] 76-76:
Expected indentation of 6 spaces but found 8


[failure] 19-19:
Expected { after 'if' condition


[failure] 141-141:
Expected { after 'if' condition

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Docker linux/amd64
🔇 Additional comments (3)
src/components/ContextMenu/ContextMenu.react.js (3)

87-105: Improved hover handling and item interaction

The new hover handler correctly updates the path state for all menu items, allowing for consistent submenu navigation. The disabled item check is also a good defensive programming practice.


145-147: Fixed path traversal logic

The improved path traversal correctly handles undefined items with the optional chaining operator.


157-171: Optimized MenuSection rendering with improved context

Precomputing itemsForLevel and parentItemCount for each level provides better context for the MenuSection component, which helps with the alignment issues mentioned in the PR objectives.

@mtrezza mtrezza closed this May 24, 2025
@mtrezza mtrezza reopened this May 24, 2025
@mtrezza
Copy link
Member

mtrezza commented May 24, 2025

@dblythy could you take a look at the review feedback?

Copy link

uffizzi-cloud bot commented May 24, 2025

Uffizzi Ephemeral Environment deployment-63880

⌚ Updated May 24, 2025, 13:12 UTC

☁️ https://app.uffizzi.com/github.com/parse-community/parse-dashboard/pull/2726

📄 View Application Logs etc.

What is Uffizzi? Learn more

Signed-off-by: Manuel <5673677+mtrezza@users.noreply.github.com>
mtrezza
mtrezza previously approved these changes May 24, 2025
Copy link

@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: 2

♻️ Duplicate comments (2)
src/components/ContextMenu/ContextMenu.react.js (2)

74-74: Add missing dependencies to useEffect

The useEffect hook is missing critical dependencies that could cause stale positioning calculations when the menu state changes.

This issue was previously identified but hasn't been addressed. The effect depends on path[level], parentItemCount, and items.length but only includes an empty dependency array.

-  }, []);
+  }, [path, level, parentItemCount, items.length]);

32-45: Guard against NaN from parseInt and improve offset logic

The positioning logic has two potential issues that could cause submenus to disappear or misalign:

  1. parseInt on computed styles can return NaN when the value is 'auto'
  2. Zero-offset handling may skip necessary repositioning

Previous reviews identified these issues but they remain unaddressed:

   if (prevEl) {
     const prevElBox = prevEl.getBoundingClientRect();
+    const prevElStyle = window.getComputedStyle(prevEl);
+    const rawTop = prevElStyle.top;
+    const prevElTop = rawTop === 'auto' ? 0 : parseInt(rawTop, 10);
+    
     const showOnRight = prevElBox.x + prevElBox.width + elBox.width < window.innerWidth;

     let proposedTop = shouldApplyOffset
-      ? prevElBox.top + offset
+      ? prevElTop + offset
       : prevElBox.top;
🧹 Nitpick comments (2)
src/components/ContextMenu/ContextMenu.react.js (2)

89-106: Improve hover behavior and disabled item handling

The unified hover behavior is a good improvement, but the implementation could be more robust.

The changes successfully unify the hover behavior for all menu items and improve disabled item handling. However, consider this minor optimization:

         const handleHover = () => {
+          if (item.disabled) return;
           const newPath = path.slice(0, level + 1);
           newPath.push(index);
           setPath(newPath);
         };

This prevents unnecessary path updates when hovering over disabled items.


13-54: Consider adding viewport overflow protection for tall menus

The positioning function handles basic viewport clamping but doesn't address extremely tall menus that might exceed the available height.

For better UX with very tall submenus, consider detecting when the menu height exceeds available space:

+ // Check if menu is too tall for viewport
+ const availableHeight = lowerLimit - upperLimit;
+ if (menuHeight > availableHeight) {
+   // Let CSS handle scrolling via maxHeight in MenuSection
+   console.warn('Menu exceeds viewport height, relying on CSS scrolling');
+ }

The existing maxHeight: '80vh' and overflowY: 'auto' in MenuSection already handle this case, so this is just for awareness.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ebc6e1c and 9f47a54.

📒 Files selected for processing (1)
  • src/components/ContextMenu/ContextMenu.react.js (5 hunks)
🧰 Additional context used
🪛 GitHub Check: Lint
src/components/ContextMenu/ContextMenu.react.js

[failure] 83-83:
Expected indentation of 4 spaces but found 6


[failure] 82-82:
Expected indentation of 6 spaces but found 8


[failure] 81-81:
Expected indentation of 6 spaces but found 8


[failure] 80-80:
Expected indentation of 6 spaces but found 8


[failure] 79-79:
Expected indentation of 6 spaces but found 8


[failure] 78-78:
Expected indentation of 6 spaces but found 8


[failure] 143-143:
Expected { after 'if' condition

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Docker linux/amd64
🔇 Additional comments (2)
src/components/ContextMenu/ContextMenu.react.js (2)

159-175: Excellent improvement to parent item count calculation

The addition of parentItemCount calculation and passing it to MenuSection components directly addresses the alignment issues mentioned in the PR objectives.

This implementation correctly:

  • Calculates parent item counts for each menu level
  • Passes the count to MenuSection for proper positioning
  • Uses stable keys for MenuSection components

The logic handles both root level (level === 0) and nested levels appropriately.


29-29:

❓ Verification inconclusive

Verify offset application logic for edge cases

The shouldApplyOffset logic may not handle all scenarios correctly, particularly when mainItemCount === 0 but offset is also 0.

The current logic mainItemCount === 0 || subItemCount > mainItemCount may cause issues when the root menu has zero offset. This could skip necessary repositioning for off-screen root menus.

Consider this improvement:

- const shouldApplyOffset = mainItemCount === 0 || subItemCount > mainItemCount;
+ const shouldApplyOffset = (mainItemCount === 0 && offset !== 0) || subItemCount > mainItemCount;

Let me verify how this function is being called to understand the offset patterns:


🏁 Script executed:

#!/bin/bash
# Check how getPositionToFitVisibleScreen is called with different parameters
rg -A 3 -B 1 "getPositionToFitVisibleScreen\(" src/

Length of output: 455


Here’s some context I need to verify before updating the comment—this will show where getPositionToFitVisibleScreen comes from and how shouldApplyOffset is used in the file:


🏁 Script executed:

#!/bin/bash
# Show import of the positioning helper
rg -n "getPositionToFitVisibleScreen" -R src/components/ContextMenu/ContextMenu.react.js

# Show surrounding lines for shouldApplyOffset definition
rg -n -C5 "const shouldApplyOffset" -R src/components/ContextMenu/ContextMenu.react.js

Length of output: 987


I’ll try again with the correct rg syntax to pull the import and the surrounding context:


🏁 Script executed:

#!/bin/bash
# Show import of the positioning helper
rg -n "getPositionToFitVisibleScreen" src/components/ContextMenu/ContextMenu.react.js

# Show surrounding lines for shouldApplyOffset definition
rg -n -C5 "const shouldApplyOffset" src/components/ContextMenu/ContextMenu.react.js

Length of output: 737


Let’s pull the function signature and how offset is used inside getPositionToFitVisibleScreen:


🏁 Script executed:

#!/bin/bash
# Show the first 40 lines of ContextMenu.react.js (function signature + setup)
sed -n '1,40p' src/components/ContextMenu/ContextMenu.react.js

# Search for all uses of `offset` in this file with context
rg -n -C3 "offset" src/components/ContextMenu/ContextMenu.react.js

Length of output: 1921


Double-check root-menu offset logic

The suggested change

- const shouldApplyOffset = mainItemCount === 0 || subItemCount > mainItemCount;
+ const shouldApplyOffset = (mainItemCount === 0 && offset !== 0) || subItemCount > mainItemCount;

is effectively a no-op when offset === 0 (both branches use prevElBox.top). Before applying this tweak, please verify in off-screen root-menu scenarios that the clamping and repositioning behave as intended.

• File: src/components/ContextMenu/ContextMenu.react.js, line 29

@mtrezza mtrezza merged commit 3fed292 into parse-community:alpha May 24, 2025
9 of 11 checks passed
parseplatformorg pushed a commit that referenced this pull request May 24, 2025
# [7.2.0-alpha.4](7.2.0-alpha.3...7.2.0-alpha.4) (2025-05-24)

### Bug Fixes

* Improperly aligned unfolding sub-items in context menu in data browser ([#2726](#2726)) ([3fed292](3fed292))
@parseplatformorg
Copy link
Contributor

🎉 This change has been released in version 7.2.0-alpha.4

@parseplatformorg parseplatformorg added the state:released-alpha Released as alpha version label May 24, 2025
parseplatformorg pushed a commit that referenced this pull request Jun 1, 2025
# [7.2.0](7.1.0...7.2.0) (2025-06-01)

### Bug Fixes

* Data browser not scrolling to top when changing filter while cell selected ([#2821](#2821)) ([c2527dc](c2527dc))
* Data browser table shows loading indicator when info panel is loading ([#2782](#2782)) ([da57e5e](da57e5e))
* Improperly aligned unfolding sub-items in context menu in data browser ([#2726](#2726)) ([3fed292](3fed292))
* Notifications fade out erratically when executing a script on large number of rows ([#2822](#2822)) ([3891381](3891381))
* Pagination does not reset to page 1 when clicking on class or filter ([#2798](#2798)) ([29d1447](29d1447))
* Saving new filter in data browser overwrites filters added in other dashboard instances ([#2769](#2769)) ([46bc154](46bc154))
* Selecting a saved filter in data browser may highlight a different filter ([#2783](#2783)) ([4c6e853](4c6e853))

### Features

* Add confirmation dialog before saving a Cloud Config parameter that has been modified since editing it ([#2770](#2770)) ([adb9b5c](adb9b5c))
* Add custom CSS styling for info panel items ([#2788](#2788)) ([f031e5d](f031e5d))
* Add relative date filter in data browser for date constraints relative to when the query is run ([#2736](#2736)) ([d9dfd69](d9dfd69))
* Add script execution on parallel batches with option `script.executionBatchSize` ([#2828](#2828)) ([cee8b8d](cee8b8d))
* Keyboard Enter key can be used to select item in data browser filter dialog field dropdown ([#2771](#2771)) ([dc14710](dc14710))
@parseplatformorg
Copy link
Contributor

🎉 This change has been released in version 7.2.0

@parseplatformorg parseplatformorg added the state:released Released as stable version label Jun 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
state:released Released as stable version state:released-alpha Released as alpha version
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Context menu offset incorrect
3 participants