Rive Animation System · 2026

Transaction
Success
System

A single Rive file driving the complete transaction success experience across six entry points, three reward types, and millions of real payments.

Context

A confirmation screen that demanded design ownership

A payment confirmation screen sounds simple: show a tick, display the amount, let the user leave. KIWI's success screen is something else. Six transaction types. Three reward tiers in strict priority order. An interactive countdown. EMI processing states. Distinct layouts for subscriptions, gift cards, and first-time milestones - all driven by runtime variables, no rebuild required.

This is the screen every KIWI user sees after every payment. The micro-interactions, the exact timing, the pixel-perfect reward moments - none of it could be approximated or described in a spec. It had to be authored and shipped as designed.

Before

Design intent that arrived by translation

The previous workflow separated authorship from outcome. Design defined how it should feel - the easing on the success burst, the coin scatter timing, the way rewards sequence in. Those decisions got handed off, interpreted in code, and what shipped was close but not right.

With six entry points, three reward types, and dozens of edge-case combinations, the margin for drift was wide. Micro-interactions are where trust is built or lost. Getting them close wasn't enough. Design needed a direct line from what it made to what users saw.

"Design had to own the motion and the timing, down to the pixel - not hand it off and hope the nuance survived translation."
The Core Flow

Loading. Burst. Rewards. Done.

Every transaction starts the same way: a processing state with the user's avatar at center, green rays shooting outward, "Do not close the screen." When the payment confirms, the screen floods with KIWI green. The checkmark resolves. Amount and recipient appear, then the top bar slides in with coin count and voucher tally. The reward sequence starts - each reward animates in as its own pill before the Pinata takes the stage.

01 — Loading
02 — Success burst
03 — Reward sequence
04 — Summary
The File

One file. Every design decision inside it.

The entire transaction success system lives in a single Rive file. Every decision in it is a design decision. The easing on the success burst, the frame where coins scatter, the timing of each reward pill entry, the greyscale transition when a Pinata expires - all authored in Rive, no app code written.

The file covers six entry points, an interactive reward sequence with three tiers, four UI components with their own internal state logic, and both loading and success phases for every transaction type. When product reviewed the combinations, they reviewed the actual file. What shipped was the file.

Inside the File

Every combination, pre-built in Rive

The artboard isn't one screen - it's a library of every possible reward state the backend can trigger. Each variant below is a live Rive artboard: reward pills with real coin counts, merged combination states, voucher capsules, share affordances.

Everything you see is data-bound. Amounts, recipient names, merchant names - runtime strings from the backend. The merchant logo, gift card brand color, coin asset - all swappable at runtime, no file changes needed. Component visibility, click interactions, whether the share button shows, whether the Pinata appears at all - engineering controls all of it through named inputs set the moment payment confirms. Design built every possible state. The backend picks which one runs.

Rive artboard view showing all reward state combinations: base reward, surprise coin, other reward, cashback & voucher, both, coinonly, voucheronly, bothnoshare, coinonly noshare, voucheronly noshare, voucherscapsule, emi reward, base plus other, base plus surprise coins, base plus other plus surprise coins, base plus emi reward.
Rive artboard - all reward state variants. Each artboard is a live Rive preview, not a static mockup. Amounts, names, coin counts, and voucher counts shown here are runtime variables. The backend passes them as integers and strings at the moment of payment. No design rebuild required to change any value.

Named inputs. Total runtime control.

Every variable below is a named input that engineering sets once, when the payment confirms. Rive reads them and routes the state machine - no app rebuild, no new file. The reward type, coin count, merchant image, share button visibility, click interactions - all runtime decisions. Design defined every state. The backend decides what the user sees.

amount
String · runtime
Transaction amount displayed in the success screen header. Passed as a formatted string ("₹50,000") from the backend.
name
String · runtime
Recipient name shown below the amount. Set per-transaction from the payment metadata.
coinCount
Integer · runtime
Number of KIWI coins earned. Drives the count-up animation and the final coin pill value. Zero means no coin reward - that branch is skipped entirely.
voucherCount
Integer · runtime
Number of vouchers rewarded. Determines whether a voucher capsule appears, and populates its count. Drives the separate voucher carousel in the Piñata reveal.
showchar
Integer · 1 / 2 / 3
Selects the Pinata character. 1 = Tomato, 2 = Strawberry, 3 = Pineapple. A single integer switched by the backend, no Rive file change required.
1 → Tomato 2 → Strawberry 3 → Pineapple
reward
Integer · 1 / 2
Determines what the Piñata reveals on burst. 1 = coin shower, 2 = voucher carousel. Independent of character selection.
1 → Coins 2 → Vouchers
neon
Boolean · subscriber flag
When the user is a KIWI Neon subscriber, flipping this single boolean converts every reward pill on the screen to its Neon variant - the black NEON badge animates into the pill. No new artboards, no structural change, no extra pills. Same component, one input, different state. The backend passes this flag once at payment time based on the user's subscription status.
false → standard pill true → NEON badge appears
neon: false → neon: true
Top Bar

One ENUM. Six widget states.

The pill at the top of the success screen - showing coin count, voucher count, and the share button - is controlled by a single ENUM on the main artboard. The backend reads the user's reward history and transaction context, then passes one of six enum values. No layout changes, no new artboard. The widget handles the rest.

widget
ENUM · artboard property
Controls which variant of the top summary bar renders. Determined by the backend based on what rewards the user earned and whether the share affordance applies to their context.
both coinonly voucheronly bothnoshare coinonly noshare voucheronly noshare

Two other values in the same data panel are also dynamic: paidtext - the payment speed shown as "Paid in ⚡1.3s" - is a string set per-transaction from payment metadata. crosssellingdue is a separate ENUM driving the cross-sell component state.

widget ENUM in the Rive data panel. The dropdown reveals all six values. As each is selected, the top bar pill transitions immediately - coins + vouchers, coins only, no share affordance - while every other input on the screen stays unchanged. The artboard responds to the enum exactly as it will at runtime.
The Rive editor, live. Left panel: every runtime input with real values - name, amount, brandname, reward, cbvalue, showchar and more. Center artboard: the full TSS animation responding to those values in real time. Right panel: all reward state combinations at a glance. Change any input, the animation updates. This is what product and engineering review before any app code is written.
State Machine

One entry. Every path.

The mainflow state machine is the brain of the file. One entry node fans out into every reward combination, every entry point variant, slider states, expiry paths - all of it. The backend sets the inputs. The state machine branches, sequences, and fires events back to the app when interactions complete. The app doesn't choreograph the animation. Rive does.

Five sub-machines run alongside mainflow: the countdown timer, show/hide toggles, the EMI slider, and the first-payment slider. Each has its own inputs and event surface. The app listens for named events - it doesn't need to know what's happening inside.

The mainflow state machine in Rive - a complex graph of 80+ nodes handling every reward combination, entry point variant, and interaction path from a single entry node.
mainflow - the primary state machine. Every node is a named state. Every arrow is a transition condition driven by runtime input values or user interaction events. The density here reflects the actual problem complexity: 6 entry points x 3 reward types x multiple combination states x slider variants. One file manages all of it declaratively.
Reward System

Three types. One sequence. Strict order.

The reward sequence isn't random. Three types can appear in any combination - Base, Other, Surprise - but they always enter in the same order. When more than one triggers, each animates in as its own pill. Adjacent pills then collide and merge into one combined count before the Pinata takes the stage.

Base
Always first
RuPay Cashback
1.5% cashback on every eligible RuPay credit card transaction. The coin pill pops in, then coins travel from the pill up to the top widget. The counter increments as each coin lands.
Other
Always second
Brand Reward
A brand-specific reward when the transaction is with a partner merchant: Swiggy cashback, NammaYatri coins, PVR vouchers. A second pill enters independently, then the two merge into one combined reward display.
Surprise
Always last
Pinata - Interactive
A character slides in from below with a 30-second countdown. Tap to burst and reveal the reward - KIWI coins or a swipeable voucher carousel. Let it expire and the character transitions to greyscale. Character type and reward type are both runtime variables.

The Pinata character and reveal are backend-driven. Rive reads two integers: character (1, 2, or 3 for Tomato, Strawberry, Pineapple) and reward type (1 for coins, 2 for vouchers). Switch between any combination without touching the file.

If the user isn't eligible for any reward, the screen handles it cleanly - the success burst fires, the amount and recipient confirm, and the screen exits with no reward UI at all. Same state machine, no separate screen.

showchar = 1
Tomato
showchar = 2
Pineapple
showchar = 3
Strawberry
All six Pinata states - active and expired greyscale

all states
active + expired

All three Pinata characters playing live in the Rive runtime. One integer - showchar - injected by the backend at payment confirmation switches the entire character. The idle bounce, the burst animation, the "Tap to open" tooltip, the countdown timer - all shared state machine logic. Nothing duplicated, nothing rebuilt. Let the countdown expire and every character shifts to greyscale. Same trigger, same transition, all three.

The Pinata character's own state machine. Each character runs through the same flow: in → midsound → midloop, branching to either burst (user taps) or deactivate (30-second timeout). This nested state machine lives inside the character component - mainflow triggers it from outside. Which character appears is determined by showchar; the flow it runs is identical for all three.
Components

Sliders for every state

Three slider components live in the same Rive file, each with a different interaction model. The EMI slider is purely state-driven - backend triggers, no user input. The other two are interactive: a swipe fires an event back to the app, or the first-payment trail leaves a gradient as the user slides through.

EMI Slider

Non-interactive. Backend-driven state transitions: Loading → In Progress → Activated. The dark pill resolves the EMI confirmation without user input.

Alert Slider

Interactive opt-in. Slide right to subscribe to a 24-hour EMI eligibility notification. The pill flips on completion: "You will be notified in 24 hours."

First Transaction Slider

Interactive milestone. The gradient trail (purple to pink to green) fires a completion event; the backend redirects the user to their first reward claim screen.

Credit Card & Gift Card

A processing state inside a processing state

Credit card and gift card payments involve multiple network calls in sequence - the payment debit and voucher purchase run on separate rails. While the user waits, a dedicated loader shows both operations at once, each with its own status: one step resolves while the next is still spinning.

The whole component is data-driven. Step headings and body lines - "Payment initiated", "Voucher purchase in progress", "Refund initiated" - are runtime strings the backend sends. State transitions fire through four triggers: trigcompdelay, trigcomprefund, trigcompfailed, trigcompsuccess. One extra detail: giftcardcolor is a runtime hex value - the brand color of the gift card merchant, injected at payment time to tint the UI.

Credit card / gift card loader in the Rive editor. The multi-step processing card shows two operations in flight at once - one resolved (✓), one spinning. All step labels are data-bound strings. The trigger set covers delay, refund, failure, and success paths. When all steps resolve, the screen transitions to the standard green success burst.
Entry Points

Same file. Different story each time.

Every transaction type KIWI processes enters the same Rive file: UPI transfers, credit card payments, Neon subscription activations, autopay setups, recharges, gift card purchases. Each has its own loading animation and success screen layout, but all branch from the same state machine. Two entry points are distinct enough to live as their own Rive pages inside the file.

Gift Card

The branded card is the hero - brand color injected via giftcardcolor at runtime. Voucher code and ID with copy affordances. WhatsApp delivery confirmation. No transaction amount; the card speaks for itself.

KIWI Neon

Vertical stripe background, KIWI NEON badge, "Annual membership activated" - a distinct visual register that marks a subscription apart from a payment. Same green success flip, completely different screen.

Summary State

Cross-sell cards, configurable by the backend.

After the success burst, the screen can enter a summary state - a scrollable row of cross-sell cards. The number of cards is a runtime variable: the layout adapts from one card to several with no design change. Cards scroll horizontally within the same screen, so the user stays in context after paying.

Audio: baked into the Rive file

Sound is built into the system, not patched in after. Multiple audio assets live inside the same .riv file, triggered by the same state machine events that drive the visuals. Engineering doesn't wire audio separately - it comes with the file.

Success burst Piñata tap & reveal Voucher appear Voucher claim Slider swipe Coin burst Reward merge
Outcome

Design shipped. Exactly as designed.

Three months from first state machine to production rollout - Rive design, developer integration, testing across all six entry points, live deployment. PMs, product designers, visual designers, and motion designers all worked from the same file throughout.

The biggest shift was ownership. Micro-interactions, animation timing, pixel-perfect states across every reward combination - design authored all of it in Rive. No spec to interpret. What the team approved in the file is what users got. That's a different kind of confidence.

Team

The people who built it

Jojo Maria George
Shubham Singh
Mehr Arora
Bala
Muhammed Sajid
Mansi
Thillana
Pratiksha
Shruti Sahu
Arpit Johri
Anurag Chaudhary
Aditya Verma