npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-highlight-text-view

v1.1.0

Published

Instagram/TikTok-style highlighted text input for React Native — rounded per-character backgrounds, editable, New Architecture (Fabric) and Expo dev build ready

Readme

react-native-highlight-text-view

Instagram/TikTok-style highlighted text input for React Native. Rounded per-character backgrounds that grow line by line as you type, drawn natively on iOS and Android for the New Architecture (Fabric).

npm version npm downloads license platforms New Architecture Expo dev build

Why

  • Story text, natively. The highlight hugs every line of text with rounded corners, like Instagram and TikTok stories, and redraws as the user types.
  • A real input. Controlled text, placeholder, maxLength, keyboard and return key props, focus/blur/submit/selection events and focus(), blur(), clear(), setText() ref methods.
  • Modern props. fontSize={32} and any React Native color ("#FF3D7F", "rgb(255, 204, 0)", "hsl(158, 64%, 52%)", "teal").
  • Fine control. Per-side padding, corner radius, background insets for fonts with tall metrics, line height, letter spacing, horizontal and vertical alignment.
  • Runtime changes. Change the font, size, colors or alignment at any time without remounting.
  • New Architecture first. A Fabric component for React Native 0.76+, Expo development builds and EAS. Fully typed.

Installation

npm install react-native-highlight-text-view
# or
yarn add react-native-highlight-text-view

React Native CLI (iOS): run cd ios && pod install after installing.

Expo:

npx expo install react-native-highlight-text-view
npx expo prebuild   # or build with EAS

This package contains native code, so it works in Expo development builds and EAS builds but not in Expo Go. No config plugin is needed.

Compatibility

| Environment | Supported | | --------------------------------------- | -------------------------- | | React Native ≥ 0.76 (New Architecture) | ✅ | | React Native with Old Architecture | ❌ (Fabric-only component) | | Expo SDK ≥ 52 (development build / EAS) | ✅ | | Expo Go | ❌ | | iOS | ✅ | | Android (minSdk 24) | ✅ |

Verified on React Native 0.87.1 (CLI) and Expo SDK 57 (React Native 0.86.3).

Quick start

import { useRef, useState } from 'react';
import {
  HighlightTextView,
  type HighlightTextViewRef,
} from 'react-native-highlight-text-view';

export default function StoryText() {
  const [text, setText] = useState('');
  const ref = useRef<HighlightTextViewRef>(null);

  return (
    <HighlightTextView
      ref={ref}
      text={text}
      onChange={(e) => setText(e.nativeEvent.text)}
      placeholder="Tap to type"
      color="#FF3D7F"
      textColor="white"
      fontSize={32}
      fontWeight="800"
      textAlign="center"
      verticalAlign="center"
      paddingLeft={10}
      paddingRight={10}
      paddingTop={4}
      paddingBottom={4}
      highlightBorderRadius={10}
      returnKeyType="done"
      onSubmitEditing={() => ref.current?.blur()}
      style={{ width: '100%', height: 240 }}
    />
  );
}

Numeric props accept numbers (fontSize={32}) or strings (fontSize="32"), and colors accept any React Native color string ("#00A4A3", "rgb(0, 164, 163)", "teal"). The string-only API of earlier versions keeps working unchanged.

The view is sized by its style (like a TextInput); the highlight is drawn only behind the text inside it.

Recipes

iOS on the left, Android on the right. All four are in the example app. Read-only views use editable={false}.

Story text

<HighlightTextView
  editable={false}
  text={'golden hour\nin lisbon'}
  color="#FF3D7F"
  textColor="#FFFFFF"
  fontSize={30}
  fontWeight="800"
  textAlign="center"
  verticalAlign="center"
  paddingLeft={10}
  paddingRight={10}
  paddingTop={4}
  paddingBottom={4}
  highlightBorderRadius={10}
  style={{ height: 130 }}
/>

Marker

A soft color plus a large backgroundInsetTop paints only the lower part of each line, like a highlighter pen.

<HighlightTextView
  editable={false}
  text="Ship the demo before Friday"
  color="#FFE066"
  textColor="#1D1D1F"
  fontSize={24}
  fontWeight="600"
  paddingLeft={3}
  paddingRight={3}
  backgroundInsetTop={14}
  highlightBorderRadius={3}
  verticalAlign="center"
  style={{ height: 92 }}
/>

Tag chips

One small read-only view per tag. Give each chip a width (the example measures the label with a hidden <Text>).

<HighlightTextView
  editable={false}
  text="#reactnative"
  color="#E0F2FE"
  textColor="#075985"
  fontSize={15}
  fontWeight="700"
  textAlign="center"
  verticalAlign="center"
  paddingLeft={10}
  paddingRight={10}
  paddingTop={6}
  paddingBottom={6}
  highlightBorderRadius={14}
  style={{ width: 130, height: 40 }}
/>

Quote

<HighlightTextView
  editable={false}
  text={'“Make it simple, but significant.”'}
  color="#14213D"
  textColor="#FCA311"
  fontFamily={Platform.select({ ios: 'Georgia', default: 'serif' })}
  fontSize={28}
  lineHeight={34}
  paddingLeft={8}
  paddingRight={8}
  paddingTop={4}
  paddingBottom={4}
  backgroundInsetTop={4}
  backgroundInsetBottom={4}
  highlightBorderRadius={4}
  verticalAlign="center"
  style={{ height: 120 }}
/>

Props

All props of View are supported too. Numeric means number | string.

| Prop | Type | Default | Description | | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | text | string | - | Controlled text value | | color | ColorValue | #FFFF00 | Highlight background color. Hex, rgb()/rgba(), hsl() or a named color (PlatformColor is not supported) | | textColor | ColorValue | - | Text color | | textAlign | TextAlignment | left | 'left', 'center', 'right', 'justify', 'flex-start', 'flex-end', 'top', 'bottom', 'top-left', 'top-center', 'top-right', 'bottom-left', 'bottom-center', 'bottom-right' | | verticalAlign | 'top' \| 'center' \| 'middle' \| 'bottom' | - | Vertical alignment. Alternative to the combined textAlign values. When omitted, iOS draws at the top and Android centers | | fontFamily | string | - | Font family name. Can be changed at runtime (no key needed) | | fontSize | Numeric | 32 | Font size in points | | fontWeight | 'normal' \| 'bold' \| '100' … '900' | normal | Font weight | | letterSpacing | Numeric | 0 | Extra space between characters, in layout points (same semantics as React Native's letterSpacing) | | lineHeight | Numeric | 0 | Line height override (0 means use default line height) | | lineSpacing | Numeric | 0 | Extra space between lines (Android) | | highlightBorderRadius | Numeric | 0 | Border radius for the highlight background | | padding | Numeric | 4 | Padding around each character highlight (expands background outward) | | paddingLeft | Numeric | - | Left padding for character highlight | | paddingRight | Numeric | - | Right padding for character highlight | | paddingTop | Numeric | - | Top padding for character highlight | | paddingBottom | Numeric | - | Bottom padding for character highlight | | backgroundInsetTop | Numeric | 0 | Shrinks background from top (useful for fonts with large vertical metrics) | | backgroundInsetBottom | Numeric | 0 | Shrinks background from bottom (useful for fonts with large vertical metrics) | | backgroundInsetLeft | Numeric | 0 | Shrinks background from left | | backgroundInsetRight | Numeric | 0 | Shrinks background from right | | editable | boolean | true | Whether the text can be edited. Same as isEditable; editable wins if both are given | | isEditable | boolean | true | Original name of editable, still supported | | autoFocus | boolean | false | Focuses the input and opens the keyboard on mount (editable views only) | | placeholder | string | - | Text shown while the input is empty | | placeholderTextColor | ColorValue | platform default | Placeholder color | | maxLength | number | no limit | Maximum number of characters the user can type (text set through text or setText() is not cut) | | autoCapitalize | 'none' \| 'sentences' \| 'words' \| 'characters' | platform default | Automatic capitalization while typing | | keyboardType | 'default' \| 'email-address' \| 'numeric' \| 'phone-pad' \| 'number-pad' \| 'decimal-pad' \| 'url' \| 'ascii-capable' \| 'numbers-and-punctuation' \| 'visible-password' | default | Keyboard to show | | returnKeyType | 'default' \| 'done' \| 'go' \| 'next' \| 'search' \| 'send' \| 'previous' \| 'join' \| 'route' \| 'none' | default | Label of the Return key. Any value other than 'default' makes Return fire onSubmitEditing instead of inserting a new line |

Events

| Event | Payload (event.nativeEvent) | Fired when | | ------------------- | ----------------------------------------------- | ---------------------------------------------------------------------------------- | | onChange | { text: string } | The text changes (typing, clear(), setText()) | | onFocus | { target: number } | The input gains focus | | onBlur | { target: number } | The input loses focus | | onSubmitEditing | { text: string } | Return is pressed while returnKeyType is set to something other than 'default' | | onSelectionChange | { selection: { start: number; end: number } } | The cursor moves or the selection changes |

Methods (ref)

Pass a ref (useRef<HighlightTextViewRef>(null)) to call:

| Method | Description | | --------------- | --------------------------------------------------------- | | focus() | Focuses the input and opens the keyboard (editable views) | | blur() | Removes focus and closes the keyboard | | clear() | Clears the text and fires onChange with '' | | setText(text) | Replaces the text and fires onChange with the new text |

TypeScript

Exported types: HighlightTextViewProps, HighlightTextViewRef, NumericProp, VerticalAlignment, AutoCapitalize, KeyboardType, ReturnKeyType, TextAlignment, the event payload types and HighlightTextViewNativeProps.

Styling details

Padding vs background insets

  • Padding props (paddingTop, paddingBottom, etc.): Expand the background outward from the text, adding extra colored area around glyphs.
  • Background inset props (backgroundInsetTop, backgroundInsetBottom, etc.): Shrink the background inward from the font's line box, creating tighter wrapping around actual glyphs.

Use case for background insets: Some fonts (like Eczar, Georgia, etc.) have large built-in vertical metrics (ascender/descender), making highlights appear too tall. Use backgroundInsetTop and backgroundInsetBottom to create a tighter fit around the visible glyphs.

Example with large-metric font:

<HighlightTextView
  fontFamily="Eczar"
  fontSize={32}
  paddingLeft={8}
  paddingRight={8}
  paddingTop={4}
  paddingBottom={4}
  backgroundInsetTop={6}
  backgroundInsetBottom={6}
  text="Tight Background"
/>

Example with touching backgrounds (tight line spacing): To make backgrounds touch vertically across multiple lines, combine lineHeight with backgroundInset:

<HighlightTextView
  fontSize={32}
  lineHeight={36} // Slightly larger than fontSize for tight spacing
  paddingLeft={8}
  paddingRight={8}
  paddingTop={4}
  paddingBottom={4}
  backgroundInsetTop={14} // Large inset reduces background height
  backgroundInsetBottom={14} // Creates room for lines to touch
  highlightBorderRadius={4}
  text="Multiple lines with touching backgrounds create smooth vertical flow"
/>

Tip: Set lineHeight to approximately fontSize + 4 to fontSize + 8, then adjust backgroundInsetTop and backgroundInsetBottom until backgrounds touch smoothly.

Auto-focusing the input

To automatically open the keyboard when the component mounts, use the autoFocus prop:

<HighlightTextView
  color="#00A4A3"
  textColor="#FFFFFF"
  fontSize={20}
  text={text}
  autoFocus={true} // Keyboard opens automatically
  onChange={(e) => setText(e.nativeEvent.text)}
  style={{ width: '100%', height: 100 }}
/>

This eliminates the need for double-tapping to open the keyboard - it will open on first render.

Changing the font at runtime

fontFamily, fontSize and fontWeight can be changed at any time; the view re-measures and redraws the highlight with the new font metrics. The key={fontFamily} workaround needed by versions before 1.0 is no longer required (it still works, it just remounts the view).

Upgrading

Upgrading from 0.1.x? Read the 1.0.0 upgrade notes: a few defaults changed (for example the iOS default textAlign is now left). All releases are listed in the CHANGELOG.

Example app

The example app is a story editor (live typing, color swatches, alignment, font size, ref methods) plus the recipes above:

yarn
yarn example ios      # or: yarn example android

Contributing

License

MIT

Made with create-react-native-library