Skip to content
Native Animation
Delivery Tracker Steps animation preview

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

npx nativeanimation add delivery-tracker-steps
Skia

Delivery Tracker Steps

A delivery timeline with a moving courier and rolling ETA, with configurable step labels, initial ETA, accent color, 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 delivery timeline with a moving courier and rolling ETA, with configurable step labels, initial ETA, accent color, and fonts.

Why this one

A typical delivery tracker has a stationary map or a disconnected checklist. Here, one UI-thread route progress drives the courier's position and tangent, the gradient trail, the remaining minutes, and the current step. The destination answers the courier's arrival with a pop and expanding ring while the last connector fills, its check draws, and the headline sharpens into “Enjoy your order.”

How it works

  1. The route is sampled at equal distances. The same samples build the Skia path and interpolate the courier's position, so the growing stroke always ends beneath the courier.
  2. A continuous shared value controls the entire journey. At 6% progress, “Picked up” advances to “On the way.” At 100%, it advances to “Delivered.”
  3. Each stage reacts to those thresholds: the connector fills downward in 400 ms, the node springs from 0.8, and its timestamp fades in. The active ring follows the stage.
  4. Each ETA digit rests at an integer and rolls only during the final quarter of a minute. The tens column moves only at its carry; distance-based opacity keeps neighboring digits from remaining visible at rest.
  5. Tapping the map toggles a separate interruptible spring. The map extends from 32% to 62% of container height (ending at 70%), and the timeline slides away.
  6. Completion draws the final Lucide check and runs a 600 ms destination ring and blurred text transition. The demo compresses twelve minutes into 24 seconds and repeats after a four-second delivered hold.

Install

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

Copy this folder without demo/. Wrap your app with GestureHandlerRootView. On web, initialize CanvasKit before importing this component (for example, use Skia's lazy web loading boundary). Font loading belongs to the host app. The included Lucide paths retain their license in LUCIDE-LICENSE.txt.

Usage

import { useEffect, useRef } from 'react';
import { DeliveryTrackerSteps, type DeliveryTrackerStepsRef } from './delivery-tracker-steps';

function OrderScreen() {
  const tracker = useRef<DeliveryTrackerStepsRef>(null);
  useEffect(() => { tracker.current?.start(); }, []);
  return <DeliveryTrackerSteps ref={tracker} />;
}

A faster route with contact actions and custom typography:

<DeliveryTrackerSteps
  ref={tracker}
  merchantName="Your neighborhood café"
  destinationLabel="8:54 AM · Oak Street"
  courierName="Marco"
  duration={24000}
  accentColor="#B91C1C"
  gradientColor="#FB923C"
  fontFamily="Geist_400Regular"
  mediumFontFamily="Geist_500Medium"
  titleFontFamily="InstrumentSerif_400Regular"
  monoFontFamily="GeistMono_400Regular"
  onMessage={openCourierChat}
  onCall={callCourier}
/>

For live delivery data, call setProgress(0…1) instead of start(). pause() cancels the timer animation, reset() returns to pickup, and toggleMap() controls expansion. Progress updates remain available with Reduced Motion enabled. This component begins at pickup; the first two steps are historical events.

Props

PropTypeDefaultDescription
merchantNamestringYour orderHeader wordmark
destinationLabelstring8:54 AM · Oak StreetArrival metadata
courierNamestringYour courierCourier name
courierInitialsstringMJAvatar initials
courierRatingstring4.9Courier rating
stepLabelsreadonly string[]Five delivery stagesLabels in order
stepTimesreadonly string[]8:31 / 8:33 / 8:41 / 8:42 / 8:54 AMStage timestamps
initialMinutesnumber12ETA; use a whole number from 1 to 99
durationnumber720000Total journey time in milliseconds
accentColorstring#B91C1CRoute, nodes, and courier; six-digit hex for halo alpha
gradientColorstring#FB923CRoute and brand gradient start
colorSchemelight / dark / autolightWarm light and dark palettes
fontFamilystringSystemBody font
mediumFontFamilystringBody fontStep and courier titles
titleFontFamilystringSystemEditorial title and wordmark
monoFontFamilystringSystemETA and timestamps
onMessage / onCall() => void—Contact actions
onStepChange(step: number) => void—Zero-based stage change callback
mapAccessibilityLabelstringExpand or collapse delivery mapMap button label
styleStyleProp<ViewStyle>—Root customization
testIDstring—Root identifier

Compatibility

Expo SDK 58, React Native 0.88.0, Reanimated 4.7.1, Worklets 0.13.0, Gesture Handler 3.3, and Skia 2.14.0. Uses the installed Expo Go stack; no extra native modules. Layout comes from the container's onLayout; give the parent a height or flex layout. Uses five Skia canvases total, including contact icons.

Supports iOS, Android, and web. The gate does not exercise an unregistered screen at runtime.

Accessibility

The map exposes a button role, expanded state, and an accessibility activation action. Contact buttons have 44-point hit areas, roles, labels, and independent press scales. Expanded-map mode removes the hidden contact controls from touch and accessibility traversal. A polite live region announces stage and whole-minute ETA updates.

Reduced Motion holds the courier at a static “On the way” position when start() is called. Host-driven progress still works; stage nodes and timestamps fade, without rolling digits, pulse, rotation, pop, blur, or an expanding destination ring. The map switches size directly.

Review notes

Code-based layout review at 390×844 and 320×694: the headline scales to fit one line, the last timestamp ends before the courier card, and the header leaves the viewer's top-right close control clear. The autoplay stage transition begins at about 1.74 seconds and settles before 3 seconds. Light effects live in radial map shaders or surface shadows; no effect uses a colored block over text.