This library was made for the Bluesky Social App. Support for this library is very much dependent on two factors:
- Do we have time to implement a feature or fix an issue?
- 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!
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.
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 installReact 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 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.
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.
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>
)
}The onSelectionChange event provides the following properties:
nativeEvent.target- The view tag identifiernativeEvent.start- The start index of the selected range (0-based)nativeEvent.end- The end index of the selected range (0-based, exclusive)
- 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
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
Bluesky Social PBC has committed to a software patent non-aggression pledge. For details see the original announcement.
Made with create-react-native-library
