Skip to content
Native Animation
Year Recap Scroll animation preview

This preview uses fictional demo content. See the props below for the customization options available in this component.

npx nativeanimation add year-recap-scroll
Skia

Year Recap Scroll

A year recap whose persistent capsules form charts and constellations, with configurable chapters, year, brand tile colors, and fonts.

$9 for this animation

Add to your project

Copy the component and its assets into your app with the Native Animation CLI, or paste the agent prompt into Claude Code, Codex or Cursor once the MCP server is connected.

About this animation

A year recap whose persistent capsules form charts and constellations, with configurable chapters, year, brand tile colors, and fonts.

Why this one

Most recap screens replace one card with another. This one preserves every shape across five charts, so the viewer can follow the data as it changes form. The favorite-hour clock adds a personal ritual; the final assembly turns the same data into a keepsake. A staggered opening fan and rolling total establish that continuity immediately.

How it works

  1. The container measures itself with onLayout; all chart coordinates use fractions of its width and height.
  2. useAnimatedScrollHandler converts the scroll offset into one continuous chapter progress from 0 to 4.
  3. Each of the sixty Skia capsules interpolates position, dimensions, rotation, and color between five destinations. Smoothstep transitions leave a twenty-percent rest around each chapter; a small index delay creates a wave.
  4. Background meshes enter above their predecessors. Editorial text uses separate entry and exit windows so consecutive headlines never overlap.
  5. Numeric columns advance only on their own carry, fade by distance, and settle on an integer. Word metrics enter with a four-pixel blur.
  6. The share card and its buttons belong to the final scroll page. Native snapping is optional; web scrolling is continuous.

Install

npx expo install react-native-reanimated react-native-worklets @shopify/react-native-skia expo-blur

Use the Reanimated/worklets configuration supplied by your Expo SDK. On web, load CanvasKit before mounting this component using Skia's WithSkiaWeb boundary. The component needs a parent with a bounded height. The fonts are supplied by your app; there are no catalog imports in the reusable files.

Usage

import { YearRecapScroll } from './year-recap-scroll';

<YearRecapScroll
  brandName="Your practice"
  onShare={() => shareRecap()}
  onSaveImage={() => exportRecapImage()}
/>;

With custom typography and controls:

const recap = useRef<YearRecapScrollRef>(null);

<YearRecapScroll
  ref={recap}
  year="2027"
  brandName="Your practice"
  fontFamily="YourSans"
  monoFontFamily="YourMono"
  titleFontFamily="YourSerif"
  italicFontFamily="YourSerifItalic"
  graphScale={0.95}
  introDuration={800}
  snapToChapters={false}
  onChapterChange={(chapter) => trackChapter(chapter)}
/>;

// UI-thread scroll animation with the measured narrative easing.
recap.current?.scrollToChapter(2, 1200);
recap.current?.replayIntro();

scrollToChapter(chapter, duration = 0) supports fractional chapters, clamps to 0–4, and is interrupted by touch or drag. replayIntro() replays the fan and first rolling total. Keep autoplay scheduling in the host; the supplied demo advances every 2.6 seconds, fades to black to reset, and stops after interaction.

Props

PropTypeDefaultPurpose
chaptersreadonly YearRecapChapter[]Five neutral recap chaptersCopy and figures for the five chart poses; missing entries use defaults
yearstring"2026"Year in the header and card
brandNamestring"Your practice"Header and summary identity
brandColorsreadonly [string, string]Pink/violetClosing sparkle tile colors
fontFamilystringSystemInterface font
monoFontFamilystringSystemCounters and tabular figures
titleFontFamilystringSystemEditorial typeface
italicFontFamilystringSystemAccent conclusion typeface
graphScalenumber1Relative graph width
introDurationnumber700Opening fan duration in milliseconds
snapToChaptersbooleantrueChapter snapping on native platforms
onChapterChange(chapter: number) => void—Nearest chapter callback on the JS thread
onInteraction() => void—Stop host autoplay after touch or drag
onShare() => void—Host share action
onSaveImage() => void—Host image export action
shareLabelstring"Share"Share label and accessible name
saveLabelstring"Save image"Save label and accessible name
styleStyleProp<ViewStyle>—Container style
testIDstring—Root test identifier

YearRecapChapter contains eyebrow, label, value, optional numericValue, headline, and conclusion. The numeric value should match the number embedded in the formatted value (for example, 4812 and "4,812"). Custom chapter text changes the narrative; the chart datasets are the deterministic example in geometry.ts.

Compatibility

Designed for Expo SDK 58, React Native 0.88.0, Reanimated 4.7.1, worklets 0.13.0, and Skia 2.14.0. Uses Expo Go bundled modules. Android uses a shared BlurTargetView and dimezisBlurViewSdk31Plus; older Android versions receive the module's translucent fallback.

Supports iOS, Android, and web. The host owns image export and platform permissions; the demo shares recap text and offers save feedback without requesting additional native modules.

Accessibility

Each chapter is a labeled header block in scroll order. Metrics use accessible formatted values. The first-page scroll prompt offers a 44-point tap alternative; buttons expose their labels and button roles. Reduced motion disables the opening fan, digit rolling, hint bobbing, and graph morphing: static poses fade across chapters, with 200 ms demo navigation. No parallax, zoom, or trails are used. Press scale uses its own shared value.

Icons: Lucide (ISC). The demo's Aurora sparkle tile uses the repository's approved brand kit.