About this animation
A premium assistant response that turns a thinking shimmer into softly revealed, structured copy.
Why this one
Most streaming treatments slide a bright rectangle over text and leave the cursor detached from the current word. This version keeps the shimmer inside the Thinking letterforms, anchors the cursor directly after the latest token, and reveals each word with a 4-point lift and a blur-to-sharp transition. Paragraphs, real bullet rows, and fenced code remain visually distinct while using the same text API.
How it works
- Each character in the thinking label derives its color and opacity from one looping shared phase, so no opaque overlay crosses the text.
- Incoming text is parsed into paragraphs, bullet rows, spacers, and fenced code without introducing a second content model.
- Every new word mounts with a short stagger, fades in, rises 4 points, and sharpens from a 4-point blur.
- The blinking cursor lives in the same wrapping row as the latest word, keeping it attached at every line length.
- A forwarded ref exposes
replay()so a host can restart the signature thinking shimmer.
Install
npx expo install react-native-reanimatedUsage
import StreamingAiReply from './StreamingAiReply';
export function AssistantMessage() {
return (
<StreamingAiReply
text={'Here is a focused plan:\n\n• Polish the core flow\n• Invite a small beta'}
done
/>
);
}Customize the surface, typography, and streaming state:
import { useRef } from 'react';
import StreamingAiReply, { type StreamingAiReplyRef } from './StreamingAiReply';
export function LiveAssistantMessage() {
const replyRef = useRef<StreamingAiReplyRef>(null);
return (
<StreamingAiReply
ref={replyRef}
text={partialReply}
thinking={!partialReply}
thinkingSeconds={3}
done={isComplete}
accentColor="#6E56FF"
surfaceColor="rgba(255,255,255,0.82)"
fontFamily="Geist-Regular"
monoFontFamily="GeistMono-Regular"
accessibilityLabel="Planning assistant response"
/>
);
}The forwarded ref exposes replay().
Props
| Prop | Type | Default | Description |
|---|---|---|---|
text | string | Required | Streamed text. Supports paragraphs, •, -, or * bullets, and fenced code. |
thinking | boolean | false | Shows the animated thinking label while the reply is empty. |
thinkingSeconds | number | 4 | Duration shown after thinking completes. |
done | boolean | false | Hides the cursor and announces the completed response. |
accentColor | string | '#6E56FF' | Thinking shimmer, status light, bullet, and cursor color. |
textColor | string | '#20202A' | Main response color. |
mutedColor | string | '#777487' | Metadata and resting thinking-label color. |
surfaceColor | string | 'rgba(255,255,255,0.82)' | Card surface color. |
fontFamily | string | System font | Response and metadata family. |
monoFontFamily | string | System font | Fenced-code family. |
style | StyleProp<ViewStyle> | — | Outer-container style. |
accessibilityLabel | string | 'Assistant reply' | Screen-reader prefix for the response. |
testID | string | — | Test identifier for the outer container. |
Compatibility
- Expo SDK 57
- React Native 0.86
- Reanimated 4.5
- iOS: supported, not yet verified on a device
- Android: supported, not yet verified on a device
- Web: supported and verified by the project gate
- Works in Expo Go because Reanimated is included in the SDK
Accessibility
The container exposes the current response as text and uses a polite live region once streaming completes. Reduced Motion keeps the hierarchy and fades words in without blur, lift, cursor blinking, or a traveling shimmer.




