Skip to content

Add onLongPress to TextInput - #59148

Draft
YevheniiKotyrlo wants to merge 2 commits into
react:mainfrom
YevheniiKotyrlo:feature/text-input-on-long-press
Draft

YevheniiKotyrlo wants to merge 2 commits into
react:mainfrom
YevheniiKotyrlo:feature/text-input-on-long-press

Conversation

@YevheniiKotyrlo

@YevheniiKotyrlo YevheniiKotyrlo commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Summary:

TextInput already handles its touches through Pressability and exposes onPress, onPressIn and onPressOut, but not onLongPress, so a component cannot tell a held press on a field from a tap. #39701 added onPress on the same grounds.

This passes onLongPress to the Pressability config TextInput already builds. A touch held past the long press delay calls it, and the release that follows calls no onPress, as on Pressable. That release is where TextInput focuses itself, so the input is focused when onLongPress fires instead; without that, a held field with contextMenuHidden on Android ends focused by the platform with no keyboard. Without onLongPress, a held press is still a press.

I need it for a one-time-code field that sets contextMenuHidden on Android and offers its own Paste on a long press.

Changelog:

[GENERAL] [ADDED] - Add onLongPress to TextInput

Test Plan:

Four Fantom cases in TextInput-itest.js under onLongPress: a touch held past the delay calls it once; it focuses the input when it fires, and the release that follows calls no onPress; a press released before the delay still calls onPress and focuses; and without onLongPress a held press still calls onPress and focuses. On main the first two fail (onLongPress is called 0 times; no focus command is sent when the delay passes); with this change the file passes, 38 of 38. yarn flow-check, yarn lint, yarn test-typescript-legacy, yarn build-types (the ReactNativeApi.d.ts snapshot gains onLongPress on TextInputBaseProps), yarn test-generated-typescript and yarn test-ci pass.

In RNTester's Playground:

function Playground() {
  const [events, setEvents] = React.useState([]);
  const record = name => setEvents(previous => [...previous, name]);
  return (
    <View style={styles.container}>
      <TextInput
        placeholder="Hold me"
        onLongPress={() => record('onLongPress')}
        onPress={() => record('onPress')}
      />
      <TextInput
        contextMenuHidden={true}
        placeholder="Hold me, menu hidden"
        onLongPress={() => record('onLongPress (menu hidden)')}
        onPress={() => record('onPress (menu hidden)')}
      />
      <RNTesterText>{events.join(', ')}</RNTesterText>
    </View>
  );
}

Holding each field for 1.5 s and lifting, in RNTester debug builds on an Android 16 (API 36) emulator: on main nothing is logged while the finger is down and onPress is logged on release; with this change onLongPress is logged while it is down and nothing on release. Both fields end focused with the keyboard up on both builds, and a tap logs onPress on both. Holding a contextMenuHidden field on its text leaves the keyboard down on both builds, because Android's own long press focuses the field first; #59130 stops that long press.

TextInput already handles its presses through Pressability and exposes
onPress, onPressIn and onPressOut, but not onLongPress, so a held press
on a TextInput cannot be told apart from a tap.

TextInput now hands onLongPress to Pressability. Once a touch is held
past the long press delay, onLongPress is called, and the release that
follows does not call onPress, as on Pressable. Without onLongPress a
held press is still a press.
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 16, 2026
@github-actions

Copy link
Copy Markdown

Warning

JavaScript API change detected

This PR commits an update to ReactNativeApi.d.ts, indicating a change to React Native's public JavaScript API.

  • Please include a clear changelog message.
  • This change will be subject to additional review.

This change was flagged as: POTENTIALLY_BREAKING

The release of a press is where TextInput focuses itself, and a long
press removes that release, so a held field was focused only by the
platform: on Android, a field with contextMenuHidden ended focused with
no keyboard. TextInput now focuses the input when onLongPress fires, as
it does on a press. Without onLongPress nothing changes.

The first onLongPress case now lifts its finger: the touch it left down
kept the responder, so the next case's touches never reached its field.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant