Skip to content
Native Animation
Trial Timeline Paywall animation preview

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

npx nativeanimation add trial-timeline-paywall

Trial Timeline Paywall

A trial paywall with a comet tracing day-by-day portals, with configurable timeline steps, copy, 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 trial paywall with a comet tracing day-by-day portals, with configurable timeline steps, copy, colors, and fonts.

Why this one

The trial becomes a journey toward full access while the reminder, charge date, and cancellation terms remain explicit. The finish is a restrained light reveal rather than a modal or confetti effect.

How it works

  1. Measure the container and reserve foreground space for the billing terms and actions.
  2. Drive the comet and three portal reveals from shared journey progress.
  3. Draw the nebula in a bounded Skia shader region while keeping copy in native layout.
  4. Let portal taps and focusStep(index) interrupt that same progress; replay() restarts the presentation.
  5. Show the completed journey immediately with reduced motion and leave purchases to the host callback.

Install

npx expo install expo-blur expo-linear-gradient react-native-gesture-handler react-native-reanimated react-native-worklets @shopify/react-native-skia

Place the component inside a GestureHandlerRootView. Copy TrialTimelinePaywall.tsx, icons.ts, and index.ts together. No assets or application imports are required. Expo Go must include the listed native modules; otherwise use a development build.

Usage

import { useRef } from 'react';
import TrialTimelinePaywall, { type TrialTimelinePaywallRef } from './trial-timeline-paywall';

const paywall = useRef<TrialTimelinePaywallRef>(null);

<TrialTimelinePaywall
  ref={paywall}
  title="A new world awaits."
  priceLead="7 days free, then"
  price="$29.99/year ($2.49/mo)"
  onStart={beginTrial}
  onClose={dismiss}
/>

Pass loaded font family names through fontFamily, boldFontFamily, titleFontFamily, and monoFontFamily. The demo uses Geist, Instrument Serif at 1.18×, and Geist Mono. The component falls back to the platform font.

Props

PropDefaultPurpose
titleA new world awaits.Editorial heading.
stepsToday, Day 5, Day 7Milestone content and portal colors. Designed for three milestones.
priceLead7 days free, thenTrial and billing lead-in.
price$29.99/year ($2.49/mo)Billing text. A leading dollar amount is emphasized; narrow proportional punctuation keeps the amount tight, and billing terms share its baseline.
ctaLabelBegin my free trialPrimary action and accessible label.
footerLinks['Promo code', 'Restore purchases']Footer action labels.
colorsDeep navy, cool blue, warm goldExisting background, glow, and cta theme controls.
startDateCurrent dateBilling date is seven calendar days later.
localeen-USLocale for the billing date.
fontFamilyPlatform fontInterface font.
boldFontFamilyInterface fontMilestone and action font.
titleFontFamilyInterface fontEditorial heading font.
monoFontFamilyPlatform fontPortal days, eyebrow, and price font.
eyebrowYOUR NEXT CHAPTERSmall brand/category text. Hidden in short containers.
closeLabelClose paywallAccessible close action label.
onStart, onClose, onPromoCode, onRestore—Action callbacks; this component does not perform purchases.
style, testID— / trial-timeline-paywallContainer styling and test identifier.

Each TrialTimelineStep retains title, description, icon, colors, and optional chargeDate. Supported Lucide icons: rocket, bell, credit-card, x. Set optional dayLabel to control the number in the portal; otherwise the number is inferred from the heading or index. A chargeDate description replaces {date} with the calculated date.

The existing ref exposes replay() and focusStep(index). Focusing a portal interrupts the same shared progress used by the comet; the plan stays readable. Invalid indices are clamped; nonfinite indices are ignored.

Compatibility

Expo SDK 58 / React Native 0.88 / Reanimated 4.7 / Skia 2.14. The atmospheric shader is restricted to a container-width × 240-point region with two noise octaves; stars share a static path, and glow strokes avoid animated blur filters. All frame updates run on the UI thread. The glass card and its BlurView both have explicit radius and clipping; Android uses a BlurTargetView with the SDK 31+ blur method and a translucent fallback on older devices.

Icons: Lucide, ISC license.

Accessibility

The composition measures its container, caps foreground content at 480 points, and uses no nested scroll views. The nebula spans the full container width and fades to transparency at its top and bottom. The scene receives the remaining vertical space; milestone descriptions stay in normal flow with a 16-point gap before billing. Descriptions use 13-point text with an 18-point line height. Short containers use a compact billing row and show the focused milestone title and description below the portals. Tap another portal to read its description; screen readers receive every milestone's full description independently.

Portal targets are at least 56 × 56, the CTA is at least 48 points high, and secondary controls are at least 44 points high. Gesture Handler handles portal/CTA taps and accessibility activation runs the same callbacks. Pressure feedback uses an interruptible spring with explicit mass 1, damping 28, and stiffness 240 (ζ ≈ 0.90).

Reduced motion shows the completed journey immediately and removes the comet, shockwaves, parallax, and sheen. Focus changes use a short transition. Demo autoplay replays through the public ref every 6.5 seconds and stops after touch or pointer input.