About this animation
A checkout that splits the price into four coins and a payment calendar, with configurable amount, payment dates, product image, and fonts.
On hosts shorter than 740 pt, the checkout content scrolls vertically, keeping the payment schedule, terms, and continue action reachable without compressing their controls.
Why this one
A typical checkout adds “or 4 payments” beneath a price. This one shows how the entire purchase becomes a schedule: a light seam divides the original number, coins trace staggered arcs, quarter-pies fill on arrival, and installment amounts roll into place. Reversing the selection collects the same coins into the full price.
How it works
onLayoutmeasures the container. A compact vertical layout fits the 320×694 demo; the larger layout adds editorial copy at 390×844. The upper-right viewer-close area stays clear.- One UI-thread progress value drives the selector, the intact price fade, light cuts, fixed 40 pt coins, flight arcs, calendar connectors, pie sectors, and amounts. React state changes only at selection or layout events.
- The whole price fades during the first 64 ms, before any coin appears. Every coin carries its complete installment amount; a gradient face, bright rim, specular highlight, and lower edge give it depth. Separate lanes stay below the selector and retrace the same arcs on reversal. The default 800 ms automated transition launches at 64/144/224/304 ms: exactly 80 ms apart. Each arc takes 368 ms; amounts settle over the final 152 ms of each arrival. Touch selection uses a critically damped spring from the current progress; dragging directly controls progress and release projects velocity.
- Each digit column rolls only on its own carry and fades neighboring digits by distance. Integer endpoints show exactly one digit, including cents. Rounded installments sum to the original integer-cent total.
- Gesture Handler composes pan and tap; accessible radio actions offer another way to choose. Button pressure has a separate shared value so a native
onPressOutcannot cancel the split. - Reduced motion crossfades the whole presentation in 200 ms, removes flights, rotation, the light seams and halo, and shows final amounts without rolling. The demo owns autoplay and cancels its timers on first contact.
Install
Copy this folder without demo/, then install compatible dependencies:
npx expo install react-native-reanimated react-native-worklets react-native-gesture-handler expo-image expo-linear-gradient @shopify/react-native-skiaUse a GestureHandlerRootView in the host app. For Skia on web, initialize CanvasKit before rendering the component (the catalog host uses withSkia / WithSkiaWeb). Include the supplied Lucide license. No remote asset or project-theme import is required by the component.
Usage
import { PayInFourSplit } from './pay-in-four-split';
export function Checkout() {
return <PayInFourSplit totalCents={129900} />;
}import { useRef } from 'react';
import { PayInFourSplit, type PayInFourSplitRef } from './pay-in-four-split';
export function CustomCheckout() {
const payment = useRef<PayInFourSplitRef>(null);
return (
<PayInFourSplit
ref={payment}
totalCents={84000}
productName="Studio camera"
productImage={require('./assets/camera.png')}
providerName="Payments"
accentColor="#7C3AED"
durationMs={800}
colorScheme="dark"
onContinue={(method) => submitPaymentMethod(method)}
/>
);
}submitPaymentMethod represents your checkout integration. The component visualizes a plan; it does not process payments. Ref methods: select('four' | 'full') and reset(). Host fonts must be loaded before rendering.
Props
| Prop | Type | Default | Purpose |
|---|---|---|---|
| totalCents | number | 129900 | Integer USD cents; bounded to 0–99999999. |
| dates | readonly tuple of four strings | Today, 11/12, 12/12, 01/11 | Calendar labels. |
| productName | string | Camera | Product card title. |
| productImage | ImageSourcePropType | — | Host-provided local artwork. |
| title | string | Choose how to pay. | Editorial heading; keep it short. |
| merchantName | string | Checkout | Merchant wordmark beside the kit aperture glyph. |
| providerName | string | Payments | Provider wordmark and control copy. |
| terms | string | 0% APR · No fees if you pay on time | Payment disclosure. |
| accentColor | string | #7C3AED | Coin, pie, indicator-label and button accent. Brand tiles retain the kit palette. |
| fontFamily | string | system | UI copy. |
| mediumFontFamily | string | fontFamily | UI emphasis. |
| monoFontFamily | string | system | Prices and changing digits. Use a monospaced font. |
| titleFontFamily | string | fontFamily | Editorial heading; demo uses Instrument Serif. |
| durationMs | number | 800 | Automated split length; minimum 300 ms. Launch stagger is 10% of this duration. |
| initialMethod | PaymentMethod | full | Initial selection. |
| colorScheme | light / dark / auto | auto | Surface theme. |
| onMethodChange | (method) => void | — | Selection event on the JS thread. |
| onInteraction | () => void | — | Touch or accessible-action notification. |
| onContinue | (method) => void | — | Checkout continuation event. |
| style | StyleProp<ViewStyle> | — | Container styling. Root defaults to flex: 1. |
| testID | string | — | Test identifier. |
Compatibility
Built for Expo SDK 58, React Native 0.88.0, Reanimated 4.7.1, worklets 0.13.0 and Skia 2.14.0. Uses installed modules supported by Expo Go. Web requires CanvasKit initialization. Icons: Lucide (ISC), copied exclusively from the project kit and rendered as local SVG image sources; the calendar uses five Skia canvases.
Accessibility
Payment methods expose radio roles, labels, selected state, focusability, and activate actions; a tap substitutes for dragging. The continuation button has a button role and label. Important method changes announce the complete plan, and the calendar exposes a polite live region with the dates and final amounts. Decorative coins and rolling digits are hidden from assistive technology. Targets are at least 44 pt. useReducedMotion() removes travel and digit rolling and uses a 200 ms fade.
Demo
The demo uses the supplied Orrin camera image, Orrin and Aster kit identities, Geist, Instrument Serif and Geist Mono. It selects installments at 1 second and returns to full payment at 4.5 seconds in a 6.5-second cycle. First touch stops autoplay for the remainder of the mounted demo. Continuing shows an accessible local confirmation.




