usePreventScroll's iOS keyboard reveal fails under React >= 19.3 in Next.js 16.3

Đang mở
#10,485 3 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức phù hợp với người mới
48/100
Loại issue
Lỗi
Độ rõ ràng
Khá rõ ràng
Mức độ hoạt động
Sôi nổi
Lĩnh vực
accessibility, frontend

Hướng nghiên cứu

Bắt đầu với bản tái hiện Next.js được liên kết tại next-repro/app/SheetDemo.jsx, sau đó so sánh với vite-repro/src/SheetDemo.jsx. Đọc các đường dẫn resize/reveal của useViewportSize và usePreventScroll rồi tái hiện vấn đề trên iOS Safari với React 19.3 trở lên. Được xem là hoàn tất khi input đang được focus được cuộn vào vùng hiển thị lúc bàn phím mở ra mà không làm hỏng hành vi trước đó của React.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

Provide a general summary of the issue here

On iOS Safari, tapping a text field inside a Modal that sizes itself from --visual-viewport-height leaves the field hidden behind the keyboard. Nothing scrolls it into view, and nothing errors.

When the keyboard opens, Safari fires one resize event on visualViewport, and two listeners run one after the other:

  • useViewportSize, added by react-aria-components on Modal mount. It calls setState, which writes --visual-viewport-height, which grows the sheet's padding and makes the body overflow.
  • usePreventScroll's reveal, added when the user tapped the field. It measures the scroller straight away and decides how far to scroll.

So the reveal only works if React commits the first listener's update before the second listener runs. That comes down to which bucket getEventPriority puts resize in.

  • react-dom 19.2 and earlier group resize with click. The update flushes in the microtask between the two listeners, so the reveal measures a scroller that has already shrunk and overflows. It scrolls correctly.
  • The React 19.3 canary moves resize in with scroll and mousemove (facebook/react#35117). The update now flushes after the whole event finishes. The reveal measures a scroller that has not shrunk yet, so scrollHeight - clientHeight is still 0, the scroll target gets clamped to 0, and scrollTo({top: 0}) does nothing.
🤔 Expected Behavior?

The focused input is correctly scrolled into view

😯 Current Behavior

See above

💁 Possible Solution

I have solved this currently by attaching a visualViewport resize listener, and setting the --visual-viewport-height property directly on the overlay DOM node.

const onResize = () => {
            overlayRef.current?.style.setProperty("--visual-viewport-height", `${visualViewport.height}px`);
        };
🔦 Context

I have built a RAC Modal sheet component for mobile users. The sheet can contain inputs, and sometimes enough inputs that the sheet can scroll, especially when the keyboard opens. The expectation is that when you focus an input and then the keyboard opens, thereby making the input end up out of the screen due to scroll, the input is scrolled back into view so the user can see what they are typing

🖥️ Steps to Reproduce

Link to repository
Link to nextjs sheet
Link to vite sheet

Version

1.17.0

What browsers are you seeing the problem on?

Safari

If other, please specify.

No response

What operating system are you using?

iOS

🧢 Your Company/Team

No response

🕷 Tracking Issue

No response

Ngôn ngữ chính
TypeScript
Star
16k
Fork
1.6k
Merge trung bình
3 ngày 9 giờ
Pull request đã merge (30 ngày)
45

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của adobe/react-spectrum

Tất cả issue của adobe/react-spectrum

Issue tương tự

Thêm issue về TypeScript

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.