Success check
Free · MITCheck or X in a circle that draws its stroke, fills, then pops with a ray-and-ring burst, for payment and booking result screens.
Installation
$ npx shadcn@latest add https://goodui.dev/r/success-check.jsonThe file lands in components/goodui/success-check.tsx and is yours to edit. With the @goodui registry added, npx shadcn@latest add @goodui/success-check works too.
Usage
import { SuccessCheck } from "@/components/goodui/success-check"
import { Button } from "@/components/ui/button"
export function PaymentResult({ ok, attempt, onRetry }: { ok: boolean; attempt: number; onRetry: () => void }) {
return (
<div className="flex flex-col items-center gap-3 text-center">
<SuccessCheck variant={ok ? "success" : "error"} playKey={attempt} size={76} />
<h2 className="text-lg font-semibold">{ok ? "Deposit paid" : "Card declined"}</h2>
<p className="text-sm text-muted-foreground">
{ok ? "$40 deposit for Thu, Nov 6 · 2:30 PM" : "Visa ending 4242 was declined. Try another card."}
</p>
{!ok && <Button onClick={onRetry}>Try again</Button>}
</div>
)
}When to use
- Result screens: payment received, booking confirmed, form submitted.
- The error counterpart on the same screen (variant="error"), so success and failure share one layout.
- Small inline ticks in a checklist that fills in, using burst={false}, a small size and a staggered delay.
- A checkbox the user toggles: use checkbox-draw.
- Confirming routine actions without changing the screen: use a toast-stack success toast.
- Showing progress through several stages before the result: use multi-step-loader, which ends on this check.
| If you need | Use |
|---|---|
| Big result icon | size={72} (default) with burst |
| Failure | variant="error" |
| Inline list ticks | size={20} burst={false} delay={i * 0.15} |
| Brand color | className="text-primary" (everything uses currentColor) |
| Replay on retry | playKey={attempt} |
Examples
Checklist ticks that land one after another
{["Deposit received", "Slot reserved", "Confirmation sent"].map((item, i) => (
<div key={item} className="flex items-center gap-2 text-sm">
<SuccessCheck size={20} burst={false} delay={i * 0.15} aria-hidden />
{item}
</div>
))}API reference
| Prop | Type | Default |
|---|---|---|
| variant "success" draws a check, "error" draws an X. | "success" | "error" | "success" |
| size Diameter in px. The burst reaches about 15% beyond it. | number | 72 |
| burst Rays and a ring that shoot outward once the mark lands. | boolean | true |
| delay Seconds before the drawing starts. | number | 0 |
| playKey Change it to play the animation again. | React.Key | — |
| label Accessible name. Defaults to "Success" or "Error". | string | — |
Also accepts every <span> attribute.
Accessibility
- The root is role="img" with aria-label "Success" or "Error"; pass label for a specific or translated name ("Payment received").
- It is not a live region. If the result appears without navigation, put the message in a role="status" element so it is announced.
- Color is not the only signal: success draws a check and error draws an X.
Motion
- The circle outline draws in 0.5 s, the tinted fill springs in from 0.6 scale at 0.28 s (stiffness 260, damping 18), then the check draws in 0.32 s from 0.42 s (the X draws its two strokes at 0.42 s and 0.58 s).
- At about 0.6 s the icon pops to 1.08x and back in 0.35 s, while a ring expands to 1.4x and fades over 0.7 s and eight rays shoot out over 0.5 s. All times shift by delay.
- Strokes stay transparent until their own draw starts, so round caps never show a dot early.
- Reduced motion: the finished icon is shown at once, with no pop and no burst. The setting is read after mount, so server and client render the same markup.
Notes for AI
Coding agents read these rules through MCP and llms.txt, or paste this page with Copy page.
- Replay by changing playKey (or variant); do not remount the parent just to replay it.
- size is a number in px; color comes from className text-* (defaults emerald for success, rose for error).
- Use burst={false} at small sizes; the burst reaches about 15% beyond the circle and can clip in tight rows.
- Pass label when the meaning is more specific than "Success" or "Error", or when your UI is not in English.
FAQ
How do I show it after a request finishes?
Render it when the result arrives (or change playKey); it plays on mount. Add confetti for big moments.
Can I change the timing?
delay shifts the whole sequence. The durations are fixed in the component; edit the t() calls in the installed file to change them.
Related
Card or overlay that ticks through steps like "Reserving slot…" with spinners, drawn checkmarks and a filling rail, ending on an animated success state.
Hand-written canvas 2D confetti with flipping paper physics, fired over the page from an element or inside a contained canvas via ref, and a no-op under reduced motion.
Checkbox whose check stroke draws itself in over a popping fill, with an indeterminate dash and an animated strike-through for checklists.
Self-contained toaster with toast() API: cards stack and expand on hover, swipe away with a drag, morph from loading to success or error for promises, and pause their timers on hover.