quasarframework / quasar

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

QTable Virtual Scroll offset by header height when closing a QDialog #17081

Open psevertson opened 1 month ago

psevertson commented 1 month ago

What happened?

When closing a QDialog on Chrome/Edge/Safari (not FireFox), the scroll position jumps down on a virtual scrolling QTable in the background.

What did you expect to happen?

The scroll should stay in the same place

Reproduction URL

https://codepen.io/psevertson/pen/jORYvBK?editors=101

How to reproduce?

  1. Open the reproduction link in Chrome/Edge/Safari (not FireFox)
  2. Make sure the table is scrolled to the top
  3. Click any row to open the dialog
  4. Close the dialog
  5. Notice the scroll has jumped down to the 2nd row

It appears that this only occurs when virtual scrolling is enabled, and the table has a shown header. The scroll gets offset to a min of what the header height is. Happens on Chrome, Edge, and Safari, but not FireFox.

Flavour

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

Areas

Components (quasar), Plugins (quasar)

Platforms/Browsers

Chrome, Safari, Microsoft Edge

Quasar info output

No response

Relevant log output

No response

Additional context

No response

Hoge42 commented 3 weeks ago

I faced the same issue as described here regarding the scroll position jumping down when a QDialog is closed. I experimented with various configurations and found a temporary workaround that might be helpful for others experiencing this problem.

By setting the noRefocus option to true on the QDialog, the scroll jump does not occur. Here's a diff of what changed:

- $q.dialog({title: "closing this will make the scroll jump down"})
+ $q.dialog({title: "closing this will make the scroll jump down", noRefocus: true})

This suggests that the focus management behavior after closing the QDialog is interfering with the virtual scroll position.

psevertson commented 3 weeks ago

Nice find! We're using a custom component, but we can put the no-refocus directly on the QDialog and it works.

Looking deeper into it, it looks like the blur() and then focus() on the <tbody class="q-virtual-scroll__content"> element is what's triggering it. Manually selecting that element in the Elements pane and calling blur() then focus() on it triggers this scroll. Even this manual trigger is only occurring on Chrome/Safari/Edge, but not Firefox, so it might be a browser issue. I'm not really sure how to dive any deeper into it.

psevertson commented 3 weeks ago

Actually, I found something else that might be helpful too: Calling focus() appears to trigger a scrollIntoView(), which is what causes this scroll. You can call focus({ preventScroll: true }) to skip that, and that bypasses the issue. Another solution is to put a scroll-margin-top onto the <tbody class="q-virtual-scroll__content">, which offsets the top of the scroll to give space for the header. We found that any value greater than the height of the header seems to work in our case, so we're using scroll-margin-top: 100vh;. It doesn't seem to have any negative side effects.