React · React Native · 16 components
Hard interactions, finished.
Animated Chorus is a set of motion components for the interactions that are hard to get right by hand: rolling numbers, streamed text, swaps that resize, sheets, pagers, swipe actions and lists that animate only what changed. One tag and your data. No provider, no setup.
npm install @kkwaenggwari/animated-chorusMeasured on this build
Chrome, 2026-09-28. Every condition and sample is in the performance guide. How it was measured
- 28.0KBKB gzip for all 16 exports
The whole web entry, minified. React is the only peer.
- 0JS frame callbacks while animating
A number, a height and a highlight changing together: the browser plays all 12 animations.
- 1React commit per value change
MotionNumberrenders when the value changes, never while it rolls. - 11React commits for 3000 streamed characters
MotionStreamappends characters directly and folds them into React a few times per second.
01Easiest
One tag and your data
Every component works on its own: no provider, wrapper component or setup call. Collections take items and renderItem, and your layout, text and styles stay yours.
- Import one component and pass a value. That is the whole integration.
- Lists, tabs and pagers read your array; keys default to
item.id. - Text stays real text: it wraps, scales with the font and can be selected.
<MotionNumber value={total} />;<MotionSwap value={status}>{label}</MotionSwap>;<MotionHeight open={open}>{details}</MotionHeight>;<MotionHighlight items={tabs} value={tab} onValueChange={setTab} />;<MotionList items={tasks} renderItem={(task) => task.title} />;<ProgressRing value={progress} />;
Six live components, and the one line of code behind each.
Preparing the example…
02Fastest
The browser plays it. React stays still.
On the web there is no animation library to load: components hand their motion to the Web Animations API, so a rolling number or a resizing panel costs no JavaScript per frame and no React render while it moves.
- 0 JS frame callbacks while 12 animations run together.
- One React commit per value change, not one per frame.
- Streamed text: 11 React commits for 3000 characters. The example below counts its own renders.
Preparing the example…
03Most stable
Interrupt anything. It never jumps.
Every new value starts from what is on screen and springs keep their speed, so rapid clicks, bursts of data and reversals look intentional. When the motion ends, nothing is left running.
- Numbers never split: remaining places slide while they roll.
- 200 new values 5 ms apart: 0 animations left afterwards and the exact final text.
- Safe under React StrictMode. In a background React Native app, motion settles to its end state.
Preparing the example…
16 components, grouped by the job they do
Numbers and text, content that changes size, selection, lists, gestures, overlays and progress. Each one has a live workbench with its props on the side.
All componentsNumbers and text
Content and size
Selection and paging
Lists
Gestures
Overlays
Progress
Put together
Complete screens that combine several components, each with its settings outside the example.
All examples- Chat answerSuggestions that fold away, an answer that streams at a steady pace and a status line that swaps.
MotionStreamMotionListMotionSwapMotionHeight - Checkout summaryQuantities, line totals and the total roll as the cart changes; the coupon notice enters and leaves; paying takes a deliberate hold.
MotionListMotionNumberMotionPresenceMotionHold - InboxFilter tabs with live counts, rows you can swipe away and a list that closes the gap.
MotionHighlightMotionListMotionSwipeMotionNumber - Photo feedSwipe through photos, jump with thumbnails, open any photo full screen and pull up its details.
MotionPagerMotionHighlightMotionZoomMotionSheet
The same import on the web and React Native
Metro selects the native implementation and web bundlers select the DOM one. Each platform plays motion the way it plays best.
// Web and React Native: the same import.
import { MotionNumber, MotionList } from '@kkwaenggwari/animated-chorus';
export function Score({ points, players }) {
return (
<>
<MotionNumber value={points} />
<MotionList items={players} renderItem={(player) => player.name} />
</>
);
}| Part | Web | React Native |
|---|---|---|
| Transforms and opacity | Web Animations API, springs sampled analytically | Animated with the native driver |
| Width and height | Web Animations API | Animated with the JS driver, because it is layout |
| Streamed text | Characters appended and faded in; a few React renders per second | A real Text, revealed without a fade |
| Sheets and zoom | A native dialog in the top layer | A transparent Modal; the back button closes it |
Start in two minutes
Install, import one component, pass a value.
npm install @kkwaenggwari/animated-chorus