Success Checkmark

( Success / Feedback / Animated )

A check that draws itself inside a soft disc, with a pulsing ring and an optional confetti burst.

Live preview and source code for Success Checkmark

A success illustration for confirmation screens: a check that draws itself inside a soft disc, a halo that keeps pulsing behind it and a confetti burst that fires once. The disc and the check spring in on mount, so the animation plays as feedback for something that just finished rather than as a decoration that was always there. Inline SVG, one accent colour, and a still prop for the finished frame.

Installation

Copy the source from the Code tab above into your project as SuccessCheckmark.tsx. The artwork is inline SVG and the copy below it is styled inline, so there is no image to host and no stylesheet to import.

It imports framer-motion for the spring entrance, the drawn check and the confetti:

Terminal
npm install framer-motion

Usage

Every prop is optional. size sets both the width and the height in pixels:

Example.tsx
import SuccessCheckmark from "./components/SuccessCheckmark";

export default function Example() {
    return (
        <SuccessCheckmark
            size={200}
            accent="#16a34a"
            title="All done"
            description="Your changes have been saved."
        />
    );
}

confetti={false} keeps the entrance but drops the burst. still renders the finished state with no animation at all, and title={null} with description={null} leaves the artwork on its own.

When to reach for it

A confirmation screen after a payment, a signup or a submitted form, where the page's whole job is to say the thing worked.

An empty state that is a good outcome: an inbox with nothing left in it, a queue that is clear, a checklist finished.

A modal or toast at a smaller size with confetti={false}, where the check should confirm without turning into a celebration.

When not to

If the action can still fail or be undone. The animation reads as final. A pending state, an optimistic update that might roll back, or a step in a longer flow all deserve something quieter.

If the outcome is routine. Confetti for a saved setting or a renamed file is more noise than feedback. Pass confetti={false} at minimum, or use a small inline icon instead.

If it needs to replay on demand. The entrance runs once when the component mounts and there is no prop to trigger it again. Changing the key to remount is the way to fire it a second time.

Accessibility

The SVG has role="img" and is labelled as a success, so the discs, the check and every confetti piece are announced as a single image rather than as parts. The title and description below it are ordinary text.

That label is fixed in the source and does not follow title, so update the aria-label in the copied file when you change the copy or the language.

The halo pulses on an infinite loop and none of the motion checks prefers-reduced-motion. Passing still gives you the completed state with no animation, which is the honest fallback: read the media query yourself and pass it through.

If the success is the result of something the user just did, the illustration alone will not announce it. Put the message in a live region and let this show the result.

Notes

The confetti pieces have their own fixed seven-colour palette and are not affected by accent, which only reaches the discs and the halo. Change the CONFETTI array in the copied file to match a brand palette.

still hides both the halo and the confetti, so it is not a paused frame of the animation but a cleaner version of the same drawing: disc, inner disc and check.

The halo is the only part that loops. Everything else settles within about a second of mount and then holds.

Unlike the other illustrations, size is used for both dimensions, so the artwork is square regardless of how much copy sits under it.