← All patterns
Success Check Reveal
A success badge springs into place while the checkmark draws itself along its path.
feedbackminimalpremiumautomatic · finite · starter · ~0.9s
Variant
The animated component in this preview is rendered from the canonical file shown here. The surrounding demo shell only provides context and is not part of the copied code.
135 lines · react + motion only
import { motion, useReducedMotion } from "motion/react";
/**
* Vibary · Success Check Reveal
*
* A success badge that springs into place while the checkmark
* draws itself along its path.
*
* Self-contained: depends only on `motion` (react ships with your app).
* Works with zero props; tune via `variant`, `size`, `color`.
* Requires the automatic JSX runtime (default since React 17).
*/
export type SuccessCheckRevealProps = {
/** Visual character of the motion. */
variant?: "subtle" | "default" | "playful";
/** Badge diameter in px. */
size?: number;
/** Badge fill color. */
color?: string;
/** Accessible label announced to screen readers. */
label?: string;
/** Fires once the checkmark has finished drawing. */
onComplete?: () => void;
};
type VariantConfig = {
scaleFrom: number;
rotateFrom: number;
spring: { type: "spring"; stiffness: number; damping: number };
checkDelay: number;
checkDuration: number;
};
const VARIANTS: Record<"subtle" | "default" | "playful", VariantConfig> = {
// No overshoot: settles straight in. For dense, frequent confirmations.
subtle: {
scaleFrom: 0.75,
rotateFrom: 0,
spring: { type: "spring", stiffness: 420, damping: 36 },
checkDelay: 0.06,
checkDuration: 0.24,
},
// Barely-there softness on landing (ratio ~0.95). All-purpose.
default: {
scaleFrom: 0.45,
rotateFrom: 0,
spring: { type: "spring", stiffness: 340, damping: 35 },
checkDelay: 0.12,
checkDuration: 0.3,
},
// A single soft rebound and a slight tilt (ratio ~0.82) — lively,
// never rubbery. Energy comes from the longer travel, not the bounce.
playful: {
scaleFrom: 0.3,
rotateFrom: -6,
spring: { type: "spring", stiffness: 400, damping: 33 },
checkDelay: 0.16,
checkDuration: 0.32,
},
};
const CHECK_PATH = "M19.5 33.5 L28 42 L44.5 24.5";
export default function SuccessCheckReveal({
variant = "default",
size = 64,
color = "#10B981",
label = "Success",
onComplete,
}: SuccessCheckRevealProps) {
const reduceMotion = useReducedMotion();
const cfg = VARIANTS[variant];
// Reduced motion: keep the information, drop the movement.
// The badge appears fully drawn with a brief opacity fade.
if (reduceMotion) {
return (
<motion.div
role="img"
aria-label={label}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.2, ease: "easeOut" }}
onAnimationComplete={onComplete}
style={{ width: size, height: size }}
>
<svg viewBox="0 0 64 64" width="100%" height="100%" fill="none">
<circle cx="32" cy="32" r="32" fill={color} />
<path
d={CHECK_PATH}
stroke="#FFFFFF"
strokeWidth={5}
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</motion.div>
);
}
return (
<motion.div
role="img"
aria-label={label}
initial={{ scale: cfg.scaleFrom, rotate: cfg.rotateFrom, opacity: 0 }}
animate={{ scale: 1, rotate: 0, opacity: 1 }}
transition={{
...cfg.spring,
// Opacity fades on its own quick curve; springing it looks muddy.
opacity: { duration: 0.18, ease: "easeOut" },
}}
style={{ width: size, height: size, transformOrigin: "50% 55%" }}
>
<svg viewBox="0 0 64 64" width="100%" height="100%" fill="none">
<circle cx="32" cy="32" r="32" fill={color} />
<motion.path
d={CHECK_PATH}
stroke="#FFFFFF"
strokeWidth={5}
strokeLinecap="round"
strokeLinejoin="round"
initial={{ pathLength: 0 }}
animate={{ pathLength: 1 }}
transition={{
delay: cfg.checkDelay,
duration: cfg.checkDuration,
ease: "easeOut",
}}
onAnimationComplete={onComplete}
/>
</svg>
</motion.div>
);
}About this pattern
Success confirmation for form submits, payments and completed tasks. The circular badge scales in on a soft spring while the checkmark strokes itself in, ending with a quiet settle. It communicates completion clearly without confetti-level drama, which keeps it usable for frequent, low-stakes confirmations as well as one-off payment moments.
Payment confirmedForm submittedTask completedSettings saved
Where it shows up
Screens we drew to show where this motion usually sits. Illustrations, not captures of any product.
- Issue tracker
Task completion check with a small, fast settle.
Related patterns
- Credit Deduct TickA usage balance ticks down to its new figure while the amount taken rises beside it and leaves.
- Clipboard Toasts StackRepeat copies push a short stack of confirmations that shuffle down and dim instead of piling up.
- Offline Banner DropA connection bar opens down out of the top edge, holds while the app retries, then retracts once it is back.