detour-onboarding
Complete onboarding guide for developers who are new to Detour, the open-source deferred deep…
Software Mansion's best practices for rich text in React Native using react-native-enriched-html (formerly react-native-enriched) and react-native-enriched-markdown. Use when building rich text editors, formatted text inputs, HTML or Markdown renderers, or any feature requiring
$ npx -y skills add software-mansion-labs/skills --skill rich-text --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/rich-textContext preview
The summary Claude sees to decide when to auto-load this skill.
Software Mansion's best practices for rich text in React Native using react-native-enriched-html (formerly react-native-enriched) and react-native-enriched-markdown. Use when building rich text editors, formatted text inputs, HTML or Markdown renderers, or any feature requiring
name: rich-text description: "Software Mansion's best practices for rich text in React Native using react-native-enriched-html (formerly react-native-enriched) and react-native-enriched-markdown. Use when building rich text editors, formatted text inputs, HTML or Markdown renderers, or any feature requiring inline styling, mentions, links, structured text editing, or Markdown display. Trigger on: 'rich text editor', 'rich text input', 'text editor', 'react-native-enriched', 'react-native-enriched-html', 'react-native-enriched-markdown', 'EnrichedTextInput', 'EnrichedText', 'EnrichedMarkdownText', 'formatted text input', 'WYSIWYG', 'mentions input', 'text formatting toolbar', 'context menu items', 'text shortcuts', 'markdown renderer', 'markdown display', 'render markdown', 'display markdown natively', 'render HTML natively', 'LaTeX math', 'GFM tables', or any request to build rich text editing or Markdown rendering in React Native."
Software Mansion's production patterns for rich text editing and rendering in React Native.
There are two libraries that cover rich text use cases. Both provide an **input** (editing) component and a **display** (rendering) component - the difference is the underlying content format:
| Library | Format | Input component | Display component | | -------------------------------- | -------- | --------------------------- | ---------------------- | | `react-native-enriched-html` | HTML | `EnrichedTextInput` | `EnrichedText` | | `react-native-enriched-markdown` | Markdown | `EnrichedMarkdownTextInput` | `EnrichedMarkdownText` |
Both libraries require the React Native New Architecture (Fabric). `react-native-enriched-html` supports iOS, Android and Web; `react-native-enriched-markdown` supports iOS, Android, macOS, and Web.
> **Package rename**: `react-native-enriched` was renamed to `react-native-enriched-html` in v1.0.0. The old npm package is deprecated and receives no updates. Migration has no breaking changes - swap the dependency and update imports. If a project still depends on `react-native-enriched`, recommend migrating.
Choose based on the **content format** your app stores and exchanges:
`EnrichedTextInput` is a native, uncontrolled rich text input. It directly interacts with platform-specific components for performance, meaning it does not use React state for its value. Its HTML output is rendered 1:1 by the companion `EnrichedText` display component.
npm install react-native-enriched-html # Expo: npx expo install react-native-enriched-html && npx expo prebuild (won't work in Expo Go)
import { EnrichedTextInput } from "react-native-enriched-html";
import type {
EnrichedTextInputInstance,
OnChangeStateEvent,
} from "react-native-enriched-html";
import { useState, useRef } from "react";
import { View, Button, StyleSheet } from "react-native";
export default function RichEditor() {
const ref = useRef<EnrichedTextInputInstance>(null);
const [stylesState, setStylesState] = useState<OnChangeStateEvent | null>();
return (
<View style={styles.container}>
<EnrichedTextInput
ref={ref}
onChangeState={(e) => setStylesState(e.nativeEvent)}
style={styles.input}
/>
<Button
title={stylesState?.bold.isActive ? "Unbold" : "Bold"}
color={stylesState?.bold.isActive ? "green" : "gray"}
onPress={() => ref.current?.toggleBold()}
/>
</View>
);
}**Toggling styles via ref**: All formatting is applied imperatively through the ref. Call `ref.current?.toggleBold()`, `ref.current?.toggleItalic()`, etc.
**Style detection via onChangeState**: The `onChangeState` callback fires whenever the style state changes (e.g., cursor moves into bold text). Each style reports three properties:
**Inline vs paragraph styles**:
**HTML output**: Get HTML via `ref.current?.getHTML()` (on-demand, returns a Promise) or the `onChangeHtml` callback (continuous, has performance cost for large documents). Prefer `getHTML()` when you only need HTML at save time. The same applies to `onChangeText` - skip it unless you need the plain text continuously.
**Setting content**: Use `defaultValue` prop for initial HTML content, or `ref.current?.setValue(html)` to update imperatively. Both accept the library's own HTML output or raw text. Arbitrary external HTML (Google Docs, Word, web pages) is normalized into the supported tag subset by default (`useHtmlNormalizer` is enabled out of the box; set it to `false` to opt out).
The
Software Mansion's set of skills for AI-assisted React Native development.
Repo: software-mansion-labs/skills
Complete onboarding guide for developers who are new to Detour, the open-source deferred deep…
Use when the user mentions migrating deep links, switching away from Branch or AppsFlyer,…
Software Mansion's guide for migrating Expo SDK apps to Meta Quest using expo-horizon…
Software Mansion's Fishjam — hosted WebRTC platform for video, audio, and one-to-many…
Node.js / TypeScript server SDK for Fishjam — backends that create rooms, mint peer tokens,…
Fishjam platform fundamentals — domain model and auth shared by all SDKs. Covers glossary…