Back to Dictionary
Status & Confirmation
●●○Customize
Context dependentSuccess Screen Transition
A dramatic transition where, upon completing a major flow, the entire screen or container slides over or fades into a dedicated success view.
Use
Completing a long multi-step wizard
Avoid
Minor setting saves (use Toast instead)
Safer Alternative
No safer default listed.
Risk Level
Low risk
Live Demo
Payment Details
What It Is
A dramatic transition where, upon completing a major flow, the entire screen or container slides over or fades into a dedicated success view.
✓When to Use
- Completing a long multi-step wizard
- Successful checkout and payment
- Account creation completion
✕When NOT to Use
- Minor setting saves (use Toast instead)
Configuration Tips
- 01Often paired with a Checkmark Draw Animation and Confetti
- 02Should block the user from navigating back into the form flow
You've Seen It In
Stripe CheckoutShopifyTypeform
AI Implementation Prompts
Move from a fast scaffold to production details, then tune timing and edge states.
When the form is submitted, fade the form out and slide a success screen up from the bottom taking over the view.
Reference Implementation
The same implementation approach used by the live preview, kept compact enough to inspect and adapt.
"use client";
import { useState, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { Check, ArrowRight, CreditCard } from 'lucide-react';
export function SuccessScreenTransitionDemo({ isPlaying = false }: { isPlaying?: boolean }) {
const [status, setStatus] = useState<'form' | 'loading' | 'success'>('form');
const handleSubmit = (e?: React.FormEvent) => {
if (e) e.preventDefault();
setStatus('loading');
setTimeout(() => setStatus('success'), 1200);
};
useEffect(() => {
if (!isPlaying) {
setStatus('form');
return;
}
const runLoop = async () => {
setStatus('form');
await new Promise(r => setTimeout(r, 600));
handleSubmit();
await new Promise(r => setTimeout(r, 2000));
};
runLoop();
const interval = setInterval(runLoop, 4000);
return () => clearInterval(interval);
}, [isPlaying]);
return (
<div className="relative flex h-64 w-full items-center justify-center overflow-hidden rounded-2xl bg-white p-6 shadow-sm ring-1 ring-stone-200">
<div className="w-full max-w-sm relative h-[340px]">
<AnimatePresence mode="wait">
{status === 'form' && (
<motion.div
key="form"
initial={{ opacity: 0, scale: 0.95 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.95 }}
transition={{ duration: 0.3 }}
className="absolute inset-0 flex flex-col rounded-3xl border border-stone-200 bg-white p-6 shadow-sm"
>
<div className="flex items-center gap-3 mb-6">
<div className="w-10 h-10 bg-stone-100 rounded-full flex items-center justify-center">
<CreditCard className="w-5 h-5 text-stone-700" />
</div>
<h3 className="text-xl font-bold text-stone-900">Payment Details</h3>
</div>
<div className="space-y-4 mb-auto">
<div className="h-12 w-full bg-stone-50 rounded-xl border border-stone-200" />
<div className="flex gap-4">
<div className="h-12 w-1/2 bg-stone-50 rounded-xl border border-stone-200" />
<div className="h-12 w-1/2 bg-stone-50 rounded-xl border border-stone-200" />
</div>
</div>
<button
onClick={handleSubmit}
className="w-full py-3.5 bg-stone-900 text-white rounded-xl font-medium flex items-center justify-center gap-2 hover:bg-stone-800 transition shadow-sm focus:ring-4 focus:ring-stone-200 outline-none mt-6"
>
<span>Pay $49.00</span>
<ArrowRight className="w-4 h-4" />
</button>
</motion.div>
)}
{status === 'loading' && (
<motion.div
key="loading"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="absolute inset-0 bg-white p-8 rounded-3xl shadow-sm border border-stone-200 flex flex-col items-center justify-center"
>
<motion.div
animate={{ rotate: 360 }}
transition={{ repeat: Infinity, duration: 1, ease: "linear" }}
className="w-12 h-12 border-[4px] border-stone-100 border-t-stone-900 rounded-full mb-6"
/>
<p className="font-medium text-stone-500 text-sm">Processing securely...</p>
</motion.div>
)}
{status === 'success' && (
<motion.div
key="success"
initial={{ opacity: 0, scale: 0.9 }}
animate={{ opacity: 1, scale: 1 }}
className="absolute inset-0 bg-[#059669] p-8 rounded-3xl shadow-lg flex flex-col items-center justify-center text-white"
>
<motion.div
initial={{ scale: 0 }}
animate={{ scale: 1 }}
transition={{ type: "spring", bounce: 0.5, delay: 0.2 }}
className="w-20 h-20 bg-white text-[#059669] rounded-full flex items-center justify-center mb-6 shadow-md"
>
<Check className="w-10 h-10 stroke-[3]" />
</motion.div>
<motion.h3
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.3 }}
className="text-2xl font-bold mb-2"
>
Payment Successful
</motion.h3>
<motion.p
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.4 }}
className="text-green-50 text-center mb-8 text-sm"
>
A receipt has been sent to your email.
</motion.p>
<motion.button
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.5 }}
onClick={() => setStatus('form')}
className="px-8 py-2.5 bg-white/20 hover:bg-white/30 rounded-xl font-medium transition-colors text-sm"
>
Done
</motion.button>
</motion.div>
)}
</AnimatePresence>
</div>
</div>
);
}