quasarframework / quasar

Quasar Framework - Build high-performance VueJS user interfaces in record time
https://quasar.dev
MIT License
25.88k stars 3.51k forks source link

QMenu remains visible for scrolled out elements #16603

Open eliaspanagiotidis opened 11 months ago

eliaspanagiotidis commented 11 months ago

What happened?

A QMenu linked to an element within a scroll area continues to stay visible even when the element is scrolled out of view, thereby obscuring other elements:

temp

What did you expect to happen?

The menu should either remain confined within the scroll area or become hidden upon scrolling. Adjusting the z-index does not appear to rectify the issue.

Reproduction URL

https://codepen.io/eliaspanagiotidis/pen/RwvjqYZ?editors=1010

How to reproduce?

Press the "Open menu" button to open the menu. Scroll up using the mouse (not the scrollbar).

Flavour

Quasar CLI with Vite (@quasar/cli | @quasar/app-vite)

Areas

Components (quasar)

Platforms/Browsers

No response

Quasar info output

No response

Relevant log output

No response

Additional context

No response

thevladisss commented 11 months ago

The easiest solution that crosses my mind is to set the absolute position on the menu, this way it is going to stay attached to the element that triggered it. Another thing I assume might work is to use Intersection API which would allow to track if menu or the element that prompted it is no longer in a viewport and then close it.

eliaspanagiotidis commented 11 months ago

Thank you, @thevladisss. I’ve tried using absolute positioning, but it doesn’t seem to make a difference. The Intersection API could be a potential solution, but it has its drawbacks. Firstly, it might be excessive if multiple elements on a page are linked with QMenus. Secondly, it doesn’t completely solve the problem, especially when the element is near the top boundary of its container or partially hidden.

Currently, my workaround involves the following steps: When a QMenu is displayed (a) the "scrollTop" of the target element's first scrollable parent is stored and (b) a scroll event listener is added to the element (the event is removed when the QMenu is hidden). When a scroll event occurs, the current location is compared with the initial one. If the distance exceeds a certain threshold, the QMenu is hidden.

This method seems to work well, I’m wondering if there’s a simpler way to implement something similar directly in the QMenu.

thevladisss commented 11 months ago

Thank you, @thevladisss. I’ve tried using absolute positioning, but it doesn’t seem to make a difference. The Intersection API could be a potential solution, but it has its drawbacks. Firstly, it might be excessive if multiple elements on a page are linked with QMenus. Secondly, it doesn’t completely solve the problem, especially when the element is near the top boundary of its container or partially hidden.

Currently, my workaround involves the following steps: When a QMenu is displayed (a) the "scrollTop" of the target element's first scrollable parent is stored and (b) a scroll event listener is added to the element (the event is removed when the QMenu is hidden). When a scroll event occurs, the current location is compared with the initial one. If the distance exceeds a certain threshold, the QMenu is hidden.

This method seems to work well, I’m wondering if there’s a simpler way to implement something similar directly in the QMenu.

Hi @eliaspanagiotidis. I've been thinking on your answer, and another suggestion I can have is to force the menu to position absolute which and use Intrsection API on the very menu, or to be more precise on its content. This would mean that if you open the menu and it is no longer in your viewport as it is absolute to its anchor element, it would would close self (in my example I d oits via ref and QMenu API).

This eliminates the problem with intersection API mentioned by you, as now it is not set onto the element that triggered the menu as there might be many.

eliaspanagiotidis commented 11 months ago

@thevladisss it seems you can't work on the QMenu content without hacks as it is handled internally by Quasar as a direct child of \<body>.

From the manual:

Don’t worry about QMenu content inheriting CSS from the container as the QMenu will be injected as a direct child of \<body> through a Quasar Portal.