Skip to content
Mobile
Skill

/rich-text

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

BOOST
From plugin
software-mansion-labs-skills
28425 skills
Install
$ npx -y skills add software-mansion-labs/skills --skill rich-text --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/rich-text

Context 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

SKILL.md

rich-text.SKILL.md
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."

Rich Text 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.

Choosing the right library

Choose based on the **content format** your app stores and exchanges:

  • **Content is HTML**, (bold, italic, mentions, links, inline images, headings, lists, text alignment, context menu items): use `react-native-enriched-html`
  • **Content is Markdown** (chat messages, documentation, AI responses): use `react-native-enriched-markdown`
  • **Don't mix the two libraries in one flow**: an input's output should feed its sibling display component directly (HTML input -> HTML display, Markdown input -> Markdown display)

react-native-enriched-html (HTML editor + display)

`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)

Basic usage

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>
  );
}

Key concepts

**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:

  • `isActive`: The style is applied at the current selection (highlight the toolbar button)
  • `isBlocking`: The style is blocked by another active style (disable the toolbar button)
  • `isConflicting`: The style conflicts with another active style (toggling it removes the conflicting style)

**Inline vs paragraph styles**:

  • Inline styles (bold, italic, underline, strikethrough, inline code) apply to the exact character range selected. With no selection, they apply to the next characters typed.
  • Paragraph styles (headings, codeblock, blockquote, lists) apply to entire paragraphs (text between newlines). If the selection spans multiple paragraphs, all are affected.
  • Only one paragraph style can be active per paragraph - all paragraph styles conflict with each other. Codeblock additionally blocks all inline 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).

Supported styles

The

Read more
Ships withsoftware-mansion-labs-skills

Software Mansion's set of skills for AI-assisted React Native development.

Get the whole plugin
Stats
284
Stars
17
Forks
Active
Maintenance
Go
Language
3d ago
Last commit
8mo ago
Created

Repo: software-mansion-labs/skills