[scroll area] Fix scrollbar visibility during touch scrolling on iOS - #5157
Conversation
commit: |
Bundle size
Check out the code infra dashboard for more information about this PR. |
✅ Deploy Preview for base-ui ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
I'm testing locally and the issue persists. When I "re-grab" the scrollarea while it's scrolling due to momentum, the thumb disappears. Simulator.Screen.Recording.-.iPhone.17.-.2026-07-02.at.10.37.14.movAlso happening in the PR preview: Simulator.Screen.Recording.-.iPhone.17.-.2026-07-02.at.10.42.27.mov |
|
It works now. I haven't tried it on Android, though. Simulator.Screen.Recording.-.iPhone.17.-.2026-07-02.at.11.13.44.mov |
There was a problem hiding this comment.
Pull request overview
Adjusts Scroll Area viewport scrolling attribution so iOS/WebKit touch scroll gestures (including cases where WebKit swallows touch/pointer events during momentum/rubber-banding) still trigger scrollbar visibility via the data-scrolling state.
Changes:
- Treat all
scrollevents as user-driven while the Scroll Area is in touch modality (skip the programmatic-scroll suppression check). - Remove
onTouchMove-based interaction attribution in the viewport (relying on touch modality instead). - Add tests covering programmatic suppression, touch-modality scroll attribution without gesture events, and modality switching back to mouse.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| packages/react/src/scroll-area/viewport/ScrollAreaViewport.tsx | Uses touchModality to ensure iOS touch scrolling always updates scroll state/attributes even when DOM events are swallowed. |
| packages/react/src/scroll-area/viewport/ScrollAreaViewport.test.tsx | Adds regression tests for programmatic-vs-touch scroll attribution and modality transitions. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Spotted while testing the new nav drawer in #5137: on iPhone, the scrollbar sometimes never appears while scrolling, depending on prior momentum/overscroll timing.
The viewport treats a scroll as user-driven only after a
wheel/touchmove/pointermove/pointerenter/keydownevent, and flips back to programmatic after 100ms without scroll events. On iOS, a touch that catches an in-flight momentum scroll or rubber-band bounce is consumed natively by WebKit and doesn't dispatch the expected touch events (confirmed by @aarongarciah —touchmoveis swallowed after re-grabbing), so the gesture gets classified as programmatic anddata-scrollingnever appears.Since no DOM event reliably marks these gestures, event-based attribution can't work on touch. Fix: while in touch modality (last pointer to interact with the root was a touch), every scroll is treated as user-driven and the programmatic check is skipped. This matches native iOS behavior, where the system scroll indicator also shows for programmatic scrolls. Programmatic suppression still applies on desktop (wheel/mouse/keyboard modality) and before the first touch (for example scroll restoration on load).
This needs manual verification on an actual iPhone, since the bug depends on native gesture handling that tests can't reproduce.
Related: #3185