Back to Dictionary
Action Feedback
●○○Ready to Use
Recommended default

Copy Confirmation Flash

A rapid, transient background color change (usually to green or a brand color) on an element that was just copied to the clipboard, providing unmistakable visual confirmation.

Use

Copy to clipboard code blocks

Avoid

Standard text selection

Safer Alternative

No safer default listed.

Risk Level

Low risk

Live Demo

npm install framer-motion

What It Is

A rapid, transient background color change (usually to green or a brand color) on an element that was just copied to the clipboard, providing unmistakable visual confirmation.

When to Use

  • Copy to clipboard code blocks
  • API key fields
  • Share links

When NOT to Use

  • Standard text selection
  • Large container elements where a full flash is overwhelming

Configuration Tips

  • 01Flash to a success color (like emerald-500/20) then fade back to transparent
  • 02Keep the flash very fast (100ms in) and the fade-out slower (500ms out) to mimic a camera flash

You've Seen It In

VercelTailwind DocsStripe Docs

AI Implementation Prompts

Move from a fast scaffold to production details, then tune timing and edge states.

Make this code block flash green momentarily when I click the copy button.

Reference Implementation

The same implementation approach used by the live preview, kept compact enough to inspect and adapt.

'use client';
import { motion, useAnimation } from 'framer-motion';
import { useState, useEffect } from 'react';
import { Copy, Check } from 'lucide-react';

export function CopyConfirmationFlashDemo({ isPlaying = false }: { isPlaying?: boolean }) {
    const controls = useAnimation();
    const [isCopied, setIsCopied] = useState(false);

    useEffect(() => {
        if (!isPlaying) {
            setIsCopied(false);
            requestAnimationFrame(() => {
                try { controls.set({ backgroundColor: 'rgba(255, 255, 255, 1)' }); } catch (e) { }
            });
            return;
        }

        const simulateCopy = async () => {
            setIsCopied(true);
            "text-stone-400 italic">// Flash success color (emerald-500/10) almost instantly
            await controls.start({
                backgroundColor: 'rgba(16, 185, 129, 0.1)',
                transition: { duration: 0.1 }
            });
            "text-stone-400 italic">// Fade back to white slowly
            await controls.start({
                backgroundColor: 'rgba(255, 255, 255, 1)',
                transition: { duration: 0.8, ease: 'easeOut' }
            });
            await new Promise((r) => setTimeout(r, 600));
            setIsCopied(false);
        };

        const interval = setInterval(simulateCopy, 2800);
        simulateCopy();

        return () => clearInterval(interval);
    }, [isPlaying, controls]);

    return (
        <div className="flex h-64 w-full items-center justify-center rounded-2xl bg-stone-50 p-6 shadow-sm ring-1 ring-stone-200">
            <motion.div
                animate={controls}
                initial={{ backgroundColor: 'rgba(255, 255, 255, 1)' }}
                className="flex items-center gap-4 rounded-lg border border-stone-200 px-4 py-3 shadow-sm bg-white"
            >
                <code className="font-mono text-xs text-stone-600 tracking-wider">npm install framer-motion</code>
                <button
                    className="flex h-8 w-8 items-center justify-center rounded-md transition-colors hover:bg-stone-100"
                    aria-label="Copy code"
                >
                    {isCopied ? (
                        <Check className="h-4 w-4 text-emerald-500" />
                    ) : (
                        <Copy className="h-4 w-4 text-stone-400" />
                    )}
                </button>
            </motion.div>
        </div>
    );
}