Shimmer Text

Description

**The "AI is thinking" shimmer, and a one-shot reveal wipe - one small component, 60fps, entirely on the UI thread.** You've seen it everywhere lately: a label like *Thinking…* or *Editing file.ts* with a bright band of light sliding across it. It reads as "something is happening" without a spinner. It's also almost always done badly - with a timer re-rendering colors, or a heavy gradient library animating on the JS thread. Here it is as one idea: 1. **The text is a mask.** A `MaskedView` uses the glyph shapes as a stencil, so every layer beneath shows *only through the letters*. 2. **A dim base color** fills those letters at rest. 3. **A bright layer, driven by one shared value**, rides above the base: - **`mode="shimmer"`** - a narrow bright band *translates* across on a loop, lighting each glyph as it passes. Perpetual, for a "working…" indicator. - **`mode="reveal"`** - a bright fill *grows* from the left with a feathered leading edge and stays lit. Text arriving on a sweep of light. One driver (a `translateX` or a width on a repeating/one-shot clock), nothing on the JS thread, and it can never desync. ### What you'll learn - Using `MaskedView` to fill text with anything (a gradient, a video, a sweep) instead of a flat color - Driving a masked highlight from a single Reanimated shared value, so the effect is a pure function of the clock - Feathering a band with a 3-stop `transparent → highlight → transparent` gradient so its edges glow instead of hard-cutting - Measuring the text once (`onLayout`) so the sweep knows exactly where to start and end ### The personality knobs Everything that defines the feel is a named prop: - `baseColor` / `highlightColor` (the rest and peak) - `duration` (sweep speed), `bandWidth` (band width in shimmer, feather size in reveal) - `gap` (the little pause a thinking indicator takes between sweeps). Swap `mode` to switch between the perpetual shimmer and the one-shot reveal. Built with **Reanimated**, **`@react-native-masked-view/masked-view`**, and **`expo-linear-gradient`** - all Expo-friendly, so it drops straight into a Snack. Works on iOS, Android, and web.

Installation

bunx @animatereactnative/cli@latest add shimmer-text

npx @animatereactnative/cli@latest add shimmer-text

yarn @animatereactnative/cli@latest add shimmer-text

pnpm dlx @animatereactnative/cli@latest add shimmer-text

Preview

Source code