Repository navigation
Implement fadingEdgeLength for ScrollView on iOS - #59003
Open
YevheniiKotyrlo wants to merge 2 commits into
Open
YevheniiKotyrlo wants to merge 2 commits into
YevheniiKotyrlo wants to merge 2 commits into
Conversation
Contributor
Author
YevheniiKotyrlo
marked this pull request as ready for review
October 12, 2026 04:52
|
Warning JavaScript API change detected This PR commits an update to
This change was flagged as: |
ScrollView declares fadingEdgeLength on its cross-platform props, but only
Android implements it: the iOS view config does not list it and iOS's props
have no field for it, so iOS drops the value.
RCTScrollViewComponentView masks the inner UIScrollView's layer with a
CAGradientLayer in which each edge fades over its own length at full
strength, which is what Android draws for {start, end}. The iOS view config
forwards fadingEdgeLength and horizontal, so the mask follows the declared
axis. The prop moves to BaseScrollViewProps, where both platforms parse it,
and to the shared props in Flow, the TypeScript types and the API snapshot.
horizontal now resets to false when the prop is removed, as its declared
default is. It reset to true, so a ScrollView whose horizontal prop was
removed kept its horizontal axis on iOS.
YevheniiKotyrlo
force-pushed
the
fix/ios-scrollview-fading-edge
branch
from
November 11, 2026 14:18
f9b6791 to
35d0736
Compare
ScrollViewTest checks that a removed horizontal resets to its declared
default and that fadingEdgeLength takes a number or a {start, end} pair
and resets to its default, so test_react_common_cxx runs both on every
pull request.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Summary:
ScrollViewdeclaresfadingEdgeLengthon its cross-platform props, but only Android implements it. On iOS the value never reaches native code — the iOS view config does not list it and the cxxHostPlatformScrollViewPropshas no field for it — so a scroller whose overflow cue is its fading edge shows none, usually with its scroll indicator turned off beside it.This implements it on iOS.
RCTScrollViewComponentViewmasks the innerUIScrollView's layer with aCAGradientLayerin which each edge fades over its own length at full strength, which is what Android draws for{start, end}(AOSP scales the fade byfadeHeight × strength, and the strength isvalue / max(start, end)); a number fades both edges. The mask is re-framed to the scroll view's bounds on scroll so it stays fixed to the viewport, mirrors with the scroll view in RTL sostartandendstay logical, and is removed for a zero pair. It sits on the scroll view rather than the component view becauseRCTViewComponentViewowns the component view'slayer.maskfor clipping rounded corners.The iOS view config now forwards
fadingEdgeLengthandhorizontal— the mask follows the declared axis, as Android does, rather than thecontentSizeheuristic, which would orient it wrongly while the content fits — and the prop moves to the shared props: fromScrollViewPropsAndroidin Flow, the TypeScript types and the API snapshot, and from Android'sHostPlatformScrollViewPropstoBaseScrollViewPropsin C++, where both platforms parse it.RCTEnhancedScrollView's safe-area padding (#59528) reads the samehorizontal, which until now isfalsefor every iOS scroller; #59194 addshorizontalto the iOS view config too.horizontalnow resets tofalsewhen the prop is removed, its declared default, as #59125 did for six other props; it reset totrue, which nothing acted on until iOS received the prop. The RNTester example is shared now and shows0,40and{start: 0, end: 80}side by side, each on a horizontal and a vertical scroller.Changelog:
[IOS] [ADDED] -
ScrollViewand the lists built on it supportfadingEdgeLengthon iOSTest Plan:
RCTScrollViewComponentViewTests, eight new cases: each edge's own length, a number on both edges, a horizontal scroll view, lengths that would overlap, zero removing the mask, the mask following the content offset, a resized scroll view, and props parsed from a raw update that removeshorizontal. No Podfile enablesReact-RCTFabric'sTestsspec, so I ran the file in RNTester'sRNTesterUnitTestson an iPhone 12 Pro Max, iOS 27.2, Xcode 27.2: 9 tests, 0 failures. Never building the mask fails the seven mask cases; never re-framing it on scroll fails the content-offset case; withhorizontalresetting totrue, the parsed case's mask stays along the width.ScrollViewTest, three new cases thattest_react_common_cxxruns: a removedhorizontalresetting to its default, andfadingEdgeLengthtaking a number or a{start, end}pair and resetting to its default. Onmainthehorizontalcase fails,reset.horizontalbeingtrueagainst the defaultfalse; with this change the scroll view's tests pass with clang 18, 12 of 12.fadingEdgeLengthon an iPhone 16 simulator, iOS 18.0, before and after: the pair. The0row is pixel-identical, and the{start: 0, end: 80}row changes only at its end edges.yarn flow-check, ESLint and Prettier on the changed JavaScript,scripts/clang-format.json the changed C++ and Objective-C++,yarn test-typescript-legacy,yarn build-types(snapshot regenerated),yarn test-generated-typescriptandyarn cxx-api-validate(Doxygen 1.16.1, Linux; the three Frameworks snapshots regenerated) pass, and ReactAndroid'srrc_scrollviewbuilds for arm64-v8a with-Werror.