From cc0b988c17534135bcc7292274b7c9f17177af74 Mon Sep 17 00:00:00 2001 From: Collin Date: Sat, 11 Jul 2026 11:58:48 +0800 Subject: [PATCH 1/2] fix(scrollview): honor programmatic scrollTo when scrollEnabled={false} ScrollViewComponentView::scrollTo() early-returned whenever scrollEnabled was false, so scrollTo (and scrollToIndex / scrollToOffset, which route through the "scrollTo" command) were dropped on a non-scrollable ScrollView / FlatList. On iOS and Android scrollEnabled only blocks user pan gestures; programmatic scroll offsets still apply. Remove the early-return; user-gesture scrolling remains gated by m_scrollVisual.ScrollEnabled (set from scrollEnabled in updateProps). Note: StartBringIntoView() and scrollToEnd()/scrollToStart() keep an analogous scrollEnabled gate; those also serve keyboard/focus paths and are left for separate discussion so keyboard scroll semantics aren't changed here. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../Fabric/Composition/ScrollViewComponentView.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp index 2e9905ed190..65aecb43d64 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp @@ -1179,10 +1179,13 @@ void ScrollViewComponentView::HandleCommand(const winrt::Microsoft::ReactNative: } void ScrollViewComponentView::scrollTo(winrt::Windows::Foundation::Numerics::float3 offset, bool animate) noexcept { - if (!std::static_pointer_cast(viewProps())->scrollEnabled) { - return; - } - + // scrollEnabled={false} must only disable *user* scroll gestures, matching + // iOS and Android where setContentOffset / scrollToOffset still work when + // scrolling is disabled. Programmatic scrolls - the scrollTo command, and + // scrollToIndex / scrollToOffset which route through it - previously hit a + // scrollEnabled early-return here and were silently dropped. User-gesture input + // is gated separately (m_scrollVisual.ScrollEnabled, set from scrollEnabled in + // updateProps), so it is safe to always honor a programmatic scroll here. m_scrollVisual.TryUpdatePosition(offset, animate); } From f5a8fccc1220c8e71734feb256eed3fc90cfacff Mon Sep 17 00:00:00 2001 From: Collin Date: Sat, 11 Jul 2026 16:42:39 +0800 Subject: [PATCH 2/2] Change files --- .../react-native-windows-fix-scrollview-programmatic.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/react-native-windows-fix-scrollview-programmatic.json diff --git a/change/react-native-windows-fix-scrollview-programmatic.json b/change/react-native-windows-fix-scrollview-programmatic.json new file mode 100644 index 00000000000..005a38d17ef --- /dev/null +++ b/change/react-native-windows-fix-scrollview-programmatic.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Honor programmatic scrollTo when scrollEnabled=false (gestures remain blocked), matching iOS/Android semantics", + "packageName": "react-native-windows", + "email": "collindanielschneide@gmail.com", + "dependentChangeType": "patch" +}