From 3f3ed7ec28361d57c9f2c8897eba361ba3f4f3ff Mon Sep 17 00:00:00 2001 From: Tony Wen Date: Sat, 4 Oct 2025 21:54:41 +1000 Subject: [PATCH 1/2] Fix Text component touch area to include padding on iOS When a Text component has padding, onPress events were not triggered when clicking in the padding area on iOS. This was caused by overly strict hit testing logic in getEventEmitterWithAttributeString. The previous logic rejected touch points where fraction == 0 or 1, which occurs when clicking in padding areas. This fix removes the fraction check and allows any valid character index within the text storage to return an event emitter. Fixes #54056 --- .../textlayoutmanager/RCTTextLayoutManager.mm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm index 3b4109c44aec..90448421b399 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm @@ -260,18 +260,18 @@ - (SharedEventEmitter)getEventEmitterWithAttributeString:(AttributedString)attri _textStorageAndLayoutManagerWithAttributesString:[self _nsAttributedStringFromAttributedString:attributedString] paragraphAttributes:paragraphAttributes size:frame.size]; + NSLayoutManager *layoutManager = textStorage.layoutManagers.firstObject; NSTextContainer *textContainer = layoutManager.textContainers.firstObject; CGFloat fraction; NSUInteger characterIndex = [layoutManager characterIndexForPoint:point - inTextContainer:textContainer - fractionOfDistanceBetweenInsertionPoints:&fraction]; + inTextContainer:textContainer + fractionOfDistanceBetweenInsertionPoints:&fraction]; - // If the point is not before (fraction == 0.0) the first character and not - // after (fraction == 1.0) the last character, then the attribute is valid. - if (textStorage.length > 0 && (fraction > 0 || characterIndex > 0) && - (fraction < 1 || characterIndex < textStorage.length - 1)) { + // Modified: Allow clicks anywhere in the text storage bounds, not just on characters + // This fixes the issue where padding areas are not clickable + if (textStorage.length > 0 && characterIndex < textStorage.length) { NSData *eventEmitterWrapper = (NSData *)[textStorage attribute:RCTAttributedStringEventEmitterKey atIndex:characterIndex effectiveRange:NULL]; From ca8c79aebcd918f0359b0503a0992533f080b53b Mon Sep 17 00:00:00 2001 From: Tony Wen <128271219+ANTI-Tony@users.noreply.github.com> Date: Sun, 12 Oct 2025 11:15:02 +1100 Subject: [PATCH 2/2] Add RNTester test cases for Text padding touch area Added two test cases to demonstrate the fix for #54056: 1. Text with Padding - Touch Area Test: Shows that both padding and text content are now clickable after the fix 2. Text Padding Boundary Test: Verifies that touches outside the text view's bounds are not captured when nested in a larger container --- .../js/examples/Text/TextExample.ios.js | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/packages/rn-tester/js/examples/Text/TextExample.ios.js b/packages/rn-tester/js/examples/Text/TextExample.ios.js index 5fdff36d3bc2..87532bdd8ea8 100644 --- a/packages/rn-tester/js/examples/Text/TextExample.ios.js +++ b/packages/rn-tester/js/examples/Text/TextExample.ios.js @@ -1574,6 +1574,77 @@ const examples = [ ); }, }, + { + title: 'Text with Padding - Touch Area Test (Issue #54056)', + name: 'textPaddingTouchArea', + render: function (): React.Node { + const [count, setCount] = React.useState(0); + return ( + + + Click on the BLUE padding area (not the text itself): + + { + setCount(count + 1); + }} + style={{ + padding: 50, + backgroundColor: 'lightblue', + fontSize: 20, + marginBottom: 10, + }}> + Click me! + + + Touch count: {count} + + + Expected: Both padding AND text should be clickable + + + ); + }, + }, + { + title: 'Text Padding Boundary Test (Issue #54056)', + name: 'textPaddingBoundaryTest', + render: function (): React.Node { + const [lastTouch, setLastTouch] = React.useState('None'); + return ( + + + The blue text should only capture touches within its bounds: + + setLastTouch('Container')}> + setLastTouch('Text (including padding)')} + style={{ + padding: 30, + backgroundColor: 'lightblue', + fontSize: 16, + }}> + Small text with padding + + + + Last touch: {lastTouch} + + + Expected: Pink area outside blue text should show "Container" + + + ); + }, + }, ...TextSharedExamples, ];