Envoy · Engineering handoff

Agent approvals: Stack flow

How a pending agent purchase is approved on Envoy Home: the fanned card stack, the full-stack list, the amount-first sheet, passkey / OTP, and the Shatter success mark. This page has the working prototype, React Native reference code built on @elixir/ui-kit/envoy, the Figma handoff and the success Lottie.

1 · Prototypes

On a laptop the flow chart sits on the left (click a box to jump to that screen) and RN notes open on the right. On a phone it's the bare device. Each card is tagged with the auth path it exercises; ↻ next to SS resets.

Stack primaryLock-screen push → sheet · Home stack, swipe to back, "1 of 9" → list · passkey, OTP, OTP error · Shatter Stack + RN notes devEvery element is outlined. Hover to preview its RN component, file, props and motion spec in the side panel; click to pin. Toggle with the RN button. Success labEvery Shatter parameter on sliders. The Lottie below was generated from its saved settings.

2 · React Native

Reference implementation that plugs into apps/elixir-card. Type-checked under strict against the app's own dependencies (RN 0.83.4, Reanimated 4.2, RNGH 2.30, lottie-react-native 7.3, @elixir/ui-kit/envoy), with 0 errors. Not yet run on a device.

EnvoyTxnAuthStack.zip codeindex.tsx (flow controller) · styles.ts · types.ts · motion.ts · tokens.proposed.ts · 9 components · README · assets README.mdIntegration, the skill deviations and why, deps, new tokens, motion spec, platform notes, checklist
Figma screenRN componentWhat to watch
H01 Home · StackCardStack · SectionHeaderTilt is positional (−0.3° / +1.7° / +3.7°), one centre. "1 of 9" is the CTA → list.
H03 Home · Stack swipeCardStack (Pan)Past 90pt → fling 260ms → back of the queue; every card rotates to its new slot angle in 460ms.
H05 Home · approved row landedApprovedRowRow drops in 380ms, then the disc scales in, then the check strokes on.
H06–H09 Notification railNotificationRailIn-screen overlay (not a Modal) · ghost cascade 0 / 70+45i ms → fill · 40pt top fade · Deny slides left, list closes up.
H10 Approval sheet · amount firstApprovalSheet · PillTimerEnvoySheet, not gorhom. The pill outline starts and ends at top centre and shrinks anticlockwise. The agent line is plain text.
H11 ApprovingDiamondLoaderThree diamonds replace the CTA label, shown for at least 900ms.
H12 Face IDauthenticate()The OS prompt from the app's passkey module; the sheet stays behind it.
H13–H15 OTPApprovalSheet → OtpStepOne hidden TextInput (oneTimeCode / sms-otp). Six digits enable Approve, with no auto-submit. Error: red underlines only.
H16 Payment successfulLottieViewsuccess-shatter.json plays once and holds the tick.
H17 Request closedApprovalSheet → ExpiredStepOpening an expired or answered request lands here.
H19 Lock screen pushinitialRequestIdTapping the push opens the sheet directly, not Home (Figma A01 → A05).

3 · Success animation

Shatter: the Envoy bird takes off, shatters, the pieces pool, a green lattice fills from the bottom, a ripple turns it solid, then the tick. Generated from the prototype's own engine, so the Lottie and the prototype match.

  • success-shatter.json: 120×120, 60fps, 2.85s, 1.9 MB. Plays in lottie-react-native, lottie-web and the LottieFiles player.
  • success-shatter.lottie: the same animation as dotLottie, 130 KB.
  • No dynamic layers. Ink #0A0A0A, green #10A37F, white tick. Dark mode needs a regenerated file.
  • Play once (loop={false}) and hold the last frame. The MP4 / WebM are for Figma, decks and the web, not the app.

4 · Figma

File 1nu4wMdlWocsKiHPNz9KmJ, page Transaction Auth. The unique screens (H01–H19) are main components, and every flow screen is an instance of one, so design changes land everywhere at once. Callouts mark Lottie and Code animation.

Engineering handoff · unique screens 711:6033Grouped: Home · Notification rail · Approval · OTP · Outcome · Other, with motion callouts on each Flow A — Stack 599:1546Every path end to end, left → right, with annotated arrows. (Flow B, Settle, is not part of this handoff.)

5 · Things that are easy to get wrong