adobe / adobe/react-spectrum

Scroll into view with sticky elements and page scrolling can cause bad-large jumps

Open
#10,182 13 comments 0 reactions 0 assignees View on GitHub
bug scrollIntoView
Dominant language
TypeScript
Stars
15.9k
Forks
1.6k
Avg merge
3d 9m
Merged PRs (30d)
59

Description

### Provide a general summary of the issue here

We have a table with the scrolling element above the table (now supported by your virtualizer, thanks!) and some sticky elements.

changing the focussed row down and up works, but when you press up going from the top table row to the table header, the page jumps and focus is now out of view.

### 🤔 Expected Behavior?

no significant jump when moving through rows

### 😯 Current Behavior

a big jump moving from the top table row to the table header.

### 💁 Possible Solution

Take this with a pinch of salt - this is what AI generated as a fix - it appears to work though:

```
+++ b/node_modules/react-aria/dist/private/utils/scrollIntoView.cjs
@@ -123,10 +123,17 @@ function $9a1324d6ffd8bbb0$export$c826860796309d1b(targetElement, opts = {}) {
if (Math.abs(originalLeft - newLeft) > 1 || Math.abs(originalTop - newTop) > 1) {
scrollParents = containingElement ? (0, $e2a63525475bbd9f$exports.getScrollParents)(containingElement, true) : [];
// scroll containing element into view first, then rescroll target element into view like the non chrome flow above
- for (let scrollParent of scrollParents)$9a1324d6ffd8bbb0$export$53a0910f038337bd(scrollParent, containingElement, {
- block: 'center',
- inline: 'center'
- });
+ for (let scrollParent of scrollParents){
+ // Saxo patch (react-spectrum #9780 edge case): only re-center the containing
+ // element when it fits within the scroll parent's viewport. Centering a
+ // containing element larger than the viewport (e.g. a full-height virtualized
+ // grid using window/parent scrolling) scrolls to its middle and moves a
+ // sticky focus target unexpectedly, causing the page to jump.
+ if (containingElement && containingElement.offsetHeight <= scrollParent.clientHeight && containingElement.offsetWidth <= scrollParent.clientWidth) $9a1324d6ffd8bbb0$export$53a0910f038337bd(scrollParent, containingElement, {
+ block: 'center',
+ inline: 'center'
+ });
+ }
for (let scrollParent of (0, $e2a63525475bbd9f$exports.getScrollParents)(targetElement, true))$9a1324d6ffd8bbb0$export$53a0910f038337bd(scrollParent, targetElement);
}
}
```

### 🔦 Context

We have this situation in our app with a table and some sticky elements, so keyboard support for the table appears broken and inaccessible.

### 🖥️ Steps to Reproduce

Go here:
https://codesandbox.io/p/sandbox/gwl9xx

1. Click setup repro
2. press up on the keyboard

or manually:
1. focus the table
2. press down until the header is out of view
3. press up until the top row is in view
4. press up again to go to the table header <-- Unexpected behaviour

### Version

1.18.0

### What browsers are you seeing the problem on?

Chrome

### If other, please specify.

_No response_

### What operating system are you using?

windows

### 🧢 Your Company/Team

Saxo Bank

### 🕷 Tracking Issue

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.