Skip to content

Proposal: Custom selection-menu items and styled-range editing for TextInput #1016

Description

@dvass88

Introduction

Every major messaging app now offers text formatting from the selection menu: select a word, tap Format, choose bold / italic / strikethrough / monospace (Signal), or a richer set with spoiler, quote, and code (Telegram, WhatsApp). On iOS this is built on UIEditMenuInteraction and attributed text editing; on Android, on ActionMode callbacks and Spannable editing.

A React Native app cannot build this using the public API of the stock TextInput — you need either a native-backed replacement/extension, a third-party native library, or a patch/fork of RN's TextInput. Two separable gaps stand in the way, and I'd like to propose that both be considered for first-class support.

Gap 1: No API to customize the selection (edit) menu

TextInput shows the system cut/copy/paste menu with no way to add, remove, or reorder items. The only public control is contextMenuHidden, which is all-or-nothing.

A minimal API sketch:

<TextInput
  editMenuItems={[
    { id: 'bold', title: 'Bold' },
    { id: 'spoiler', title: 'Spoiler' },
  ]}
  onEditMenuItemPress={({ id, selectionStart, selectionEnd }) => { ... }}
/>

Native mapping is direct: UITextViewDelegate.textView(_:editMenuForTextIn:suggestedActions:) on iOS, ActionMode.Callback on Android. This half is small, self-contained, and useful far beyond formatting (translate, define, custom actions on selection).

Gap 2: No supported styled-range editing model

RN renders styled ranges beautifully in <Text> (nested children → NSAttributedString / SpannableString), but there is no supported way to edit styled text. Nested Text children inside TextInput exist in the wild, but only function as a fully controlled input — every keystroke round-trips through JS and back — which produces cursor lag (react/react-native#44157) and, under Fabric, silently dropped updates when the event count is stale.

The ask here is not necessarily a full rich-text editor in core — it could be an attributedText-style prop with range annotations, or simply a blessed, Fabric-safe mechanism that libraries can build on without patching internals.

Prior art

The pattern across all of them is the same: this can only be done by reimplementing or patching the native text field, which is exactly the argument for core (or a core-blessed extension point).

Why core

Styled-in-place text and selection-menu actions are baseline behaviors of the native text stacks on both platforms — table stakes for messaging, notes, and editor apps, which are a large share of what gets built with React Native. Today the answer to "can I add a Format menu like WhatsApp's?" is "not with the stock TextInput's public API," and that gap is wide enough that every serious team pays it separately.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions