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]; 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, ];