Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

84 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

image

Note about support for this library

This library was made for the Bluesky Social App. Support for this library is very much dependent on two factors:

  1. Do we have time to implement a feature or fix an issue?
  2. How important is the feature to Bluesky or does it fix an issue present in Bluesky?

If there are features that you want to see in this library that don't already exist and likely (or definitely) do not greatly improve the experience in Bluesky, please feel free to submit a PR! Of course, you should also feel free to make feature suggestions or bug reports as well, and whenever free time is available the might be worked on. Just know it might take some time.

Thank you!

React Native UITextView

The Text implementation in React Native much more closely resembles UILabel on iOS. Unfortunately, this prevents the user from being able to highlight text for selection. The only copy behavior that is possible is to copy the entire block of text.

UITextView however allows a user to highlight portions of the text block for copying, translation, or other native capabilities.

React Native UITextView takes advantage of UITextView to allow for both types of copying on iOS: highlight and copy or the current, UILabel behavior to just copy the entire block of text.

Installation

Warning

The final version of this package that supports the old React Native architecture is 1.4.0. All versions 2.x and higher support only the new architecture. Unfortunately I do not have time to maintain support for both architectures. Version 1.4.0 however is stable and - aside from the still missing features from the base <Text> component, should work the same as 2.x and higher.

Note

Version 2.4.0 of @bsky.app/react-native-uitextview is tested against React Native 0.86 and supports React Native 0.81.5 and newer. React Native's new-architecture text layout APIs can change between releases; compatibility issues are most likely to arise in RNUITextViewShadowNode.cpp.

yarn add @bsky.app/react-native-uitextview
cd ios
pod install

Limitations

React Native UITextView can - for the most part - be used as a drop-in replacement for existing blocks of Text. However, there are a few limitations:

  • A few styles have not yet been implemented, but all should be possible.

Usage

Usage of this component is the same as the base React Native Text component. It can be imported as Text from @bsky.app/react-native-uitextview, so in most cases you only need to replace your current Text import with this one.

Aside from the few limitations above, all of the existing styles and props that you are using for Text should work. On non-iOS platforms, the base React Native Text will always be used. On iOS, the base React Native Text component will be used unless the selectable and the uiTextView props are both true.

import {UITextView as Text} from '@bsky.app/react-native-uitextview'

function SomeView() {
  return (
    <View style={{flex: 1}}>
      <Text
        style={{color: 'green', lineHeight: 20, fontSize: 14}}
        selectable
        uiTextView>
        This is some highlightable text! It uses UITextView
      </Text>
      <Text
        style={{color: 'blue', lineHeight: 20, fontSize: 14}}
        selectable // Note we do not add the uiTextView prop
      >
        This text still uses the base Text component. It can only be copied.
      </Text>
      <Text
        style={{color: 'red', lineHeight: 20, fontSize: 14}}
        uiTextView // Note we do not add the selectable prop
      >
        This text still uses the base Text component. It can't be highlighted or
        copied at all.
      </Text>
    </View>
  )
}

Nesting of UITextView components is supported. For example, if you have styles that should be applied only to a portion of the text, or an onPress callback to add to a link.

<Text style={{fontSize: 14}} selectable uiTextView>
  This is some text that's highlightable with{' '}
  <Text
    style={{color: 'blue', textDecorationLine: 'underline'}}
    onPress={() => Linking.openURL('https://google.com')}>
    a link
  </Text>
  .
</Text>

Inline views are also supported and participate in text measurement and wrapping:

<Text selectable uiTextView>
  Selectable text{' '}
  <View
    style={{
      paddingHorizontal: 5,
      paddingVertical: 2,
      borderRadius: 999,
      backgroundColor: '#e5e7eb',
    }}>
    <Text style={{fontSize: 12}}>1/3</Text>
  </View>
</Text>

Pressable UITextView text uses the same rounded gray press highlight as React Native Text. The highlight appears immediately, remains visible for at least 130 ms on a quick tap, and covers non-pressable nested spans belonging to the same pressable parent. Set suppressHighlighting to disable the visual feedback without disabling onPress or onLongPress.

Selection Detection

UITextView supports native selection change events via the onSelectionChange callback. This provides real-time notifications when the user selects or deselects text, eliminating the need for polling-based selection detection.

Usage

import {UITextView as Text} from '@bsky.app/react-native-uitextview'

function SelectableText() {
  const [selectedText, setSelectedText] = React.useState('')

  return (
    <Text
      selectable
      uiTextView
      onSelectionChange={event => {
        const {start, end} = event.nativeEvent
        // Extract selected text from your content string
        const text = content.substring(start, end)
        setSelectedText(text)
      }}>
      Selectable text content
    </Text>
  )
}

Event Properties

The onSelectionChange event provides the following properties:

  • nativeEvent.target - The view tag identifier
  • nativeEvent.start - The start index of the selected range (0-based)
  • nativeEvent.end - The end index of the selected range (0-based, exclusive)

Notes

  • Works correctly with multibyte characters (e.g., Arabic, emojis)
  • Only available on iOS when using uiTextView={true}
  • The event fires even when selection is cleared (start === end), including when the library clears it itself on a tap outside the text view
  • The event fires on every selection-edge adjustment — dragging a selection handle to extend by a few characters will fire many times. Consumers driving expensive work off this event should debounce

Contributing

Contributions are always welcome - and encouraged. Please note however that it might take time for PRs to be reviewed and merged, and they might not be merged at all. This library was created to support text selection in the Bluesky Social App. Contributions that may affect the proper functioning of the component in Bluesky will not be merged.

Some ideas for great contributions that we do not have time to properly implement:

  • Full support for all RN styles
  • Accessibility improvements

License

Bluesky Social PBC has committed to a software patent non-aggression pledge. For details see the original announcement.


Made with create-react-native-library

About

A UITextView implementation for React Native that allows for full text highlighting/selection, native translations, etc.

Topics

Resources

Contributing

Stars

413 stars

Watchers

9 watching

Forks

Releases

Packages

Used by

Contributors

Languages