Expo module for iOS and Android built on react-native-webview. It renders
HTML with advanced text selection, custom context menus, and persistent
highlighting via Rangy. Serialize, sync, restore selections and more
Web is not supported.
Try it in Expo Go → Select a passage, pick a color from the native menu, clear the highlights and bring them back. No install, no build.
| You need | This module |
|---|---|
| Highlights that survive a remount, a restart, or a new device | Yes — serialize them, store the string, pass it back |
| Rich content: articles, chapters, anything already HTML | Yes — you hand it HTML and CSS |
| Your own selection menu | Yes — native menu items, your actions |
| A tap target on each highlight, with its position | Yes — onHighlightPressed reports the rects |
Selection on a native <Text> tree |
No — this renders a WebView |
| Web support | No — iOS and Android only |
| Selection or highlights inside a PDF | No |
Basic usage from the example app: selecting text, highlight entrance and exit animations, the focus effect, and focusing and removing a highlight.
| iOS | Android |
|---|---|
|
|
npm install @majornutcracker/react-native-selectable-text
This is an Expo module. In bare React Native projects,
install and configure expo
first, then run npx pod-install.
Peer dependencies: expo, react, react-native, and
react-native-webview ^13.16.1 (>=13.16.1 <14; v14 ships incompatible types).
import * as React from "react";
import {
SelectableTextView,
SelectableTextViewRef,
Highlighter,
} from "@majornutcracker/react-native-selectable-text";
const highlighters: Highlighter[] = [
{
name: "yellow-highlighter",
options: { type: "background-color", color: "yellow" },
},
];
export default function Screen({ saved }: { saved?: string }) {
const ref = React.useRef<SelectableTextViewRef>(null);
return (
<SelectableTextView
ref={ref}
content="<h1>Hello</h1><p>Select some text and highlight it.</p>"
css=".content { padding: 16px; font-size: 18px; }"
highlighters={highlighters}
// What a previous session stored. Read once, when the view mounts.
initialHighlights={saved}
onHighlightsChange={(highlights) => {
// Persist this serialized string to restore highlights later.
console.log(highlights);
}}
onHighlightPressed={(highlight) => {
console.log("pressed", highlight.id, highlight.name, highlight.text);
}}
/>
);
}
// From anywhere, with the ref:
// ref.current?.highlightSelection("yellow-highlighter");
// ref.current?.setHighlights(payload); // replace them; "" clears
// ref.current?.undo(); // and redo(), and clearHistory()Store the string onHighlightsChange reports, hand it back through
initialHighlights on the next mount, and the highlights come back where the
reader left them. On a view that is already on screen, setHighlights()
replaces them and undo() / redo() walk a history the view keeps for you —
see the API reference.
- API reference — every prop, callback, and ref method, plus highlighter styles and animations, fonts, error codes, ignored elements, and the content trust boundary.
example/— a runnable reader app with three documents, each a different HTML/CSS design, showing animated highlight entrances and exits. Open the native projects withyarn open:ios/yarn open:android.
Contributions are welcome! See CONTRIBUTING.md for setup, workflow, and commit conventions.
Hit a blocker, need a feature, or found a bug? Open an issue — we follow them closely and keep improving the library.
MIT — see LICENSE.
This package bundles Rangy (© Tim Down, MIT). See THIRD-PARTY-NOTICES.md.

