Star ๅކๅฒ่ถ‹ๅŠฟ
ๆ•ฐๆฎๆฅๆบ: GitHub API ยท ็”Ÿๆˆ่‡ช Stargazers.cn
README.md

https://github.com/user-attachments/assets/ecc58493-07f3-4ac1-8bb8-e36d237cbd5c

expo-content-transition

Native content transitions for React Native + Expo.

Features

  • One component โ€” NumericText โ€” that rolls, scales, blurs, and staggers its glyphs, natively
  • Digits align around the decimal separator, so 123.45 โ†’ 123.46 only animates the final character
  • Non-numeric content aligns from the left, so shared prefixes stay put
  • Every dial you'd want: roll distance, entry scale, bounce, per-glyph blur, stagger, direction
  • monospacedDigits keeps digit columns from shifting as neighbours change
  • Value changes cross the bridge; measuring, diffing, and animating all happen natively

Installation

bun install expo-content-transition

This module includes native iOS and Android code, so you need to prebuild and run on a device or simulator โ€” Expo Go is not supported.

bunx expo prebuild
bunx expo run:ios
bunx expo run:android

If you've already prebuilt your project, just re-run expo run:ios / expo run:android after installing.

Usage

import { NumericText } from 'expo-content-transition';

Quick Start

import { NumericText } from 'expo-content-transition';
import { Pressable, Text, View } from 'react-native';

export default function Counter() {
  const [value, setValue] = React.useState(0);

  return (
    <View>
      <NumericText value={value} color="#fff" fontSize={72} monospacedDigits />
      <Pressable onPress={() => setValue((v) => v + 1)}>
        <Text>Increment</Text>
      </Pressable>
    </View>
  );
}

API

<NumericText>

PropTypeDefaultDescription
valuestring | numberโ€”The text to display. Only this crosses the bridge when it changes โ€” the rest happens natively
colorstringplatformAny React Native colour; defaults to the platform's primary label colour
fontSizenumberโ€”Font size in scale-independent pixels
fontWeightFontWeight"normal"normal, bold, or 100โ€“900
fontStyleFontStyle"normal"normal or italic
fontFamilystringโ€”Resolved like a <Text> โ€” expo-font families, bundled fonts, or platform built-ins
letterSpacingnumberโ€”Extra spacing between characters, in points
monospacedDigitsbooleanfalseUniform-width digits, so unchanged columns never shift
alignmentAlignment"start"start, center, or end; also settable via style.textAlign
decimalSeparatorstring"."The character separating whole and fractional parts; characters align around it
styleTextStyleโ€”Text props apply to the glyphs; everything else styles the view

Transition props

PropTypeDefaultDescription
directionDirection"auto"auto rolls up as the value grows and down as it shrinks; force up/down otherwise
durationnumber420Nominal transition duration in milliseconds; scales every internal spring
bouncenumber0.46Roll overshoot, 0โ€“0.95; only the roll bounces
enterScalenumber0.4Entry size of an arriving glyph; 1 leaves a pure roll
travelnumber0.333Roll distance as a fraction of the line height; 0 removes vertical movement
blurbooleantrueBlurs each glyph in proportion to how far through its transition it is
blurIntensitynumber1Scales the blur, 0โ€“8; 0 is equivalent to blur={false}
maxBlurRadiusnumberunboundedCeiling on the blur radius, in dp โ€” lets intensity be pushed without turning to soup
clipbooleantrueClips each glyph to its own line box so rolling glyphs don't overlap neighbours
animatedbooleantrueSet to false to apply values instantly; the first value never animates either way

blur requires Android 12 (API 31); it's silently ignored on lower Android versions and works everywhere on iOS.

Full Example

A stopwatch that updates ten times a second โ€” transitions blend instead of queueing up behind one another:

import { NumericText } from 'expo-content-transition';
import { Pressable, Text, View } from 'react-native';

function pad(n: number) {
  return String(n).padStart(2, '0');
}

export default function Stopwatch() {
  const [running, setRunning] = React.useState(false);
  const [ticks, setTicks] = React.useState(0);

  React.useEffect(() => {
    if (!running) return;
    const id = setInterval(() => setTicks((t) => t + 1), 100);
    return () => clearInterval(id);
  }, [running]);

  const formatted = `${pad(Math.floor(ticks / 600))}:${pad(Math.floor(ticks / 10) % 60)}.${ticks % 10}`;

  return (
    <View>
      <NumericText value={formatted} color="#f2f4f8" fontSize={48} fontWeight="500" monospacedDigits />
      <Pressable onPress={() => setRunning((r) => !r)}>
        <Text>{running ? 'Stop' : 'Start'}</Text>
      </Pressable>
    </View>
  );
}

Requirements

  • Expo SDK with a development build or bare workflow (Expo Go is not supported)
  • iOS and Android โ€” fully native on both
  • Web falls back to a plain <Text>, without transitions

License

MIT ยฉ 2026 Ritesh

ๅ…ณไบŽ About

๐Ÿš€ Native content transitions for React Native + Expo.

่ฏญ่จ€ Languages

Swift31.2%
TypeScript31.1%
Kotlin29.0%
JavaScript8.2%
Ruby0.5%

ๆไบคๆดป่ทƒๅบฆ Commit Activity

ไปฃ็ ๆไบค็ƒญๅŠ›ๅ›พ
่ฟ‡ๅŽป 52 ๅ‘จ็š„ๅผ€ๅ‘ๆดป่ทƒๅบฆ
9
Total Commits
ๅณฐๅ€ผ: 9ๆฌก/ๅ‘จ
Less
More

ๆ ธๅฟƒ่ดก็Œฎ่€… Contributors