Skip to content
Craft

Craft · 試作

Click-to-copy email

Tap the address and it's on your clipboard — the icon pops to a check and the button confirms 'Copied', then settles back. The same control ships on the contact page.

  • GSAP
  • Clipboard API
  • A11y

Live demo

Click to copy

Live · try it with mouse, touch, or keyboard

How it’s built

  • Copy goes through the async Clipboard API, with a hidden-textarea + execCommand fallback for older or insecure contexts so it still works everywhere.
  • On success the icon swaps Copy → Check and pops with a GSAP back.out(3) scale; the address itself stays select-all for manual copy.
  • The result is announced through a polite aria-live status region, so screen-reader users hear 'Copied' without focus moving.
  • Reduced motion → the icon swaps instantly with no pop.

Accessibility

  • Result announced via a polite aria-live region — no focus move needed.
  • Address stays select-all for manual copy; reduced motion → instant icon swap.

Source

The exact component, read straight from the repo at build. Requires gsap and @gsap/react.

CopyEmailDemo.tsx
"use client";

import { CopyEmail } from "@/components/ui/copy-email";
import { profile } from "@/lib/profile";

const EMAIL = profile.links.email.replace("mailto:", "");

/**
 * Craft-stage wrapper for the {@link CopyEmail} control — the same click-to-copy
 * component shipped on /contact, presented here as an inspectable demo. Centered
 * in the violet stage with a one-line prompt above it.
 */
export function CopyEmailDemo() {
  return (
    <div className="flex h-full w-full flex-col items-center justify-center gap-4 p-6">
      <p className="font-mono text-xs uppercase tracking-[0.22em] text-foreground/55">
        Click to copy
      </p>
      <CopyEmail email={EMAIL} />
    </div>
  );
}

Usage

usage.tsx
import { CopyEmailDemo } from "@/components/craft/CopyEmailDemo";

<CopyEmailDemo />

Why these choices? The timing, easing, and reduced-motion rules behind every demo live in the motion skill file.

Read it