{
 "$schema": "../../schema.json",
 "schema": "fundus/1",
 "id": "kopieren-feedback",
 "name": "Kopieren-Feedback",
 "name_en": "Copy to clipboard feedback",
 "kurz": "Kopieren bestätigt sich direkt am Knopf: Häkchen, Tooltip oder rollender Text, nach 2 s zurück.",
 "kategorie": "Mikroanimationen",
 "kategorie_slug": "mikroanimationen",
 "kategorie_nr": 9,
 "bau_chat": "C4",
 "prioritaet": "A",
 "trendstatus": "etabliert",
 "belegstatus": "belegt",
 "website_belege": 4,
 "stimmung": [
  "präzise",
  "verspielt"
 ],
 "stimmung_roh": [
  "freundlich",
  "funktional"
 ],
 "technik": [
  "vanilla-js",
  "css",
  "svg",
  "motion"
 ],
 "technik_gruppen": [
  "css",
  "js",
  "canvas",
  "andere"
 ],
 "leistungskosten": "niedrig",
 "steckbrief": {
  "beschreibung": "Ein Klick auf „Kopieren“ legt E-Mail-Adresse, Code oder Link mit navigator.clipboard.writeText in die Zwischenablage. Die Bestätigung erscheint genau dort, wo geklickt wurde: Das Icon wird zum Häkchen, das Label zu „Kopiert“. Nach etwa 2 s kehrt der Ausgangszustand zurück. Scheitert das Kopieren, sieht man einen Hinweis.",
  "warum_es_wirkt": "Kopieren ist eine unsichtbare Aktion. Die Bestätigung am Ort macht sie sichtbar, ohne Toast und ohne den Blick vom Inhalt zu lösen.",
  "wann_einsetzen": "E-Mail-Adresse im Kontaktbereich (statt nur mailto), Code-Snippets, Teilen-Links, Gutscheincodes.",
  "wann_nicht": "Wenn Kopieren nicht die Hauptabsicht ist. Dann ist ein normaler Link besser.",
  "varianten": [
   "Icon-Tausch: Kopier-Icon verschwimmt und schrumpft, Häkchen zeichnet sich per pathLength ein",
   "Tooltip „Kopiert!“ steigt über dem Knopf auf und verblasst",
   "Text-Roll: der Wert selbst rollt zu „Kopiert“",
   "Cursor-Label wechselt (siehe kontextueller-cursor)"
  ],
  "umsetzung": "await navigator.clipboard.writeText(text); zeile.dataset.zustand = 'kopiert'; live.textContent = 'E-Mail-Adresse kopiert'; clearTimeout(t); t = setTimeout(() => zeile.dataset.zustand = 'bereit', 2000). Den Timeout bei erneutem Klick löschen. CSS: .icon { transition: opacity .2s, filter .2s, scale .2s } [data-zustand=kopiert] .icon-kopie { opacity: 0; filter: blur(4px); scale: .6 }. Häkchen mit pathLength=\"1\" am Pfad: stroke-dasharray: 1; stroke-dashoffset: 1; im Zustand kopiert stroke-dashoffset: 0 mit 300 ms und 100 ms Verzögerung. Rückfall für alte Browser: execCommand('copy'), sonst Text markieren und Hinweis zeigen.",
  "mobil": "Identisch. Der Knopf braucht mindestens 44 px Zielfläche und darf nur als Icon erscheinen, wenn der Name für Screenreader bleibt.",
  "reduzierte_bewegung": "Nur Überblenden ohne Blur, Scale, Aufsteigen oder Rollen. Das Häkchen erscheint fertig gezeichnet.",
  "barrierefreiheit": "Statusmeldung per aria-live=\"polite\". Der Button-Name bleibt gleich („E-Mail-Adresse kopieren“), nur die sichtbare Bestätigung wechselt. Im Fehlerfall den Text markieren und den Hinweis vorlesen lassen."
 },
 "messwerte": {
  "easing": "",
  "dauer_ms": "Rückkehr nach 2000 (Tailwind, Cursor, Collins) bzw. 1000 (Raycast)",
  "stagger_ms": "",
  "distanz": "",
  "sonstiges": "Timeout wird bei erneutem Klick zurückgesetzt (Cursor, Collins)",
  "herkunft": "beobachtet",
  "quelle": "https://tailwindcss.com/_next/static/chunks/122cqq07nrvzt.js"
 },
 "kurve": {
  "bezier": [
   0.16,
   1.0,
   0.3,
   1.0
  ],
  "css": "cubic-bezier(0.16, 1, 0.3, 1)",
  "name": "expo.out",
  "dauer_ms": 2000
 },
 "gesehen_bei": [
  {
   "seite": "Motion Examples: Copy button",
   "url": "https://motion.dev/examples/react-copy-button",
   "auszeichnung": "",
   "beobachtung": "Laut Beschreibung: Icon-Tausch, Blur-Übergänge, pathLength-Häkchen; APIs AnimatePresence, whileHover, whileTap, layout (Code hinter Paywall).",
   "art": "demo"
  },
  {
   "seite": "Tailwind CSS",
   "url": "https://tailwindcss.com/",
   "auszeichnung": "",
   "beobachtung": "Copy-Button: navigator.clipboard.writeText, Zustand 'kopiert' für 2000 ms (setTimeout 2e3).",
   "art": "website"
  },
  {
   "seite": "Cursor",
   "url": "https://cursor.com/",
   "auszeichnung": "",
   "beobachtung": "Copy-Button: writeText, Bestätigung, Rücksetzen nach 2000 ms (Timeout-Ref wird bei erneutem Klick gelöscht).",
   "art": "website"
  },
  {
   "seite": "Raycast",
   "url": "https://www.raycast.com/",
   "auszeichnung": "",
   "beobachtung": "copyToClipboard: Bestätigungszustand für 1000 ms.",
   "art": "website"
  },
  {
   "seite": "Collins",
   "url": "https://www.wearecollins.com/",
   "auszeichnung": "",
   "beobachtung": "E-Mail-Button: status 'success' mit Label 'Copied', nach 2000 ms zurück.",
   "art": "website"
  }
 ],
 "tutorials": [
  {
   "titel": "Motion: Copy button",
   "url": "https://motion.dev/examples/react-copy-button"
  }
 ],
 "kombinierbar_mit": [
  "button-zustaende",
  "text-roll-hover"
 ],
 "urls": {
  "detail": "https://cecodesign.de/lab/fundus/mikroanimationen/kopieren-feedback/",
  "meta": "https://cecodesign.de/lab/fundus/mikroanimationen/kopieren-feedback/meta.json",
  "demo": "https://cecodesign.de/lab/fundus/mikroanimationen/kopieren-feedback/demo"
 },
 "herkunft": {
  "quelldateien": [
   "hover.json",
   "patch-belege-1.json"
  ],
  "pruefnotizen": [
   "patch-belege-1.json: 4 Produktionsbelege; reale Haltezeit meist 2 s."
  ]
 },
 "bau": {
  "status": "fertig",
  "kurz": "Kopieren bestätigt sich direkt am Knopf: Häkchen, Tooltip oder rollender Text, nach 2 s zurück.",
  "demo": true,
  "abhaengigkeiten": [],
  "werte": {
   "easing": "cubic-bezier(0.16, 1, 0.3, 1) (expo.out) für alle Bewegungen",
   "haltezeit_ms": "2000 (Tailwind, Cursor, Collins), umschaltbar auf 1000 (Raycast); erneuter Klick setzt den Timeout zurück",
   "icon_tausch": "opacity, filter blur(4px), scale 0.6 in 200 ms; Label kopieren/Kopiert mit blur(4px) und 4 px Versatz in 200 ms",
   "haekchen": "pathLength=1, stroke-dasharray 1, stroke-dashoffset 1 → 0 in 300 ms nach 100 ms Verzögerung",
   "tooltip": "Blase steigt 8 px auf, opacity 0 → 1 in 300 ms, verblasst in 200 ms",
   "text_roll": "Wert rollt um eine Zeile (1lh = 1.25em, Maske height: 1lh) in 500 ms zu „Kopiert“ mit Häkchen",
   "druck": "scale 0.94 in 150 ms",
   "fehler": "Rückfall execCommand('copy'); scheitert auch das, Text markieren und Hinweis 4000 ms zeigen",
   "reduziert": "nur opacity, 150 ms linear, Häkchen sofort ganz"
  },
  "ausloeser": "klick",
  "touch": "Identisch per Tippen; Knopf wird zur 44-px-Icon-Fläche, der Name bleibt für Screenreader erhalten.",
  "reduziert": "Kein Blur, kein Scale, kein Aufsteigen, kein Rollen: Zustände blenden in 150 ms linear über, das Häkchen erscheint fertig gezeichnet.",
  "korrekturen": {
   "beschreibung": "Ein Klick auf „Kopieren“ legt E-Mail-Adresse, Code oder Link mit navigator.clipboard.writeText in die Zwischenablage. Die Bestätigung erscheint genau dort, wo geklickt wurde: Das Icon wird zum Häkchen, das Label zu „Kopiert“. Nach etwa 2 s kehrt der Ausgangszustand zurück. Scheitert das Kopieren, sieht man einen Hinweis.",
   "warum_es_wirkt": "Kopieren ist eine unsichtbare Aktion. Die Bestätigung am Ort macht sie sichtbar, ohne Toast und ohne den Blick vom Inhalt zu lösen.",
   "wann_einsetzen": "E-Mail-Adresse im Kontaktbereich (statt nur mailto), Code-Snippets, Teilen-Links, Gutscheincodes.",
   "wann_nicht": "Wenn Kopieren nicht die Hauptabsicht ist. Dann ist ein normaler Link besser.",
   "varianten": [
    "Icon-Tausch: Kopier-Icon verschwimmt und schrumpft, Häkchen zeichnet sich per pathLength ein",
    "Tooltip „Kopiert!“ steigt über dem Knopf auf und verblasst",
    "Text-Roll: der Wert selbst rollt zu „Kopiert“",
    "Cursor-Label wechselt (siehe kontextueller-cursor)"
   ],
   "umsetzung": "await navigator.clipboard.writeText(text); zeile.dataset.zustand = 'kopiert'; live.textContent = 'E-Mail-Adresse kopiert'; clearTimeout(t); t = setTimeout(() => zeile.dataset.zustand = 'bereit', 2000). Den Timeout bei erneutem Klick löschen. CSS: .icon { transition: opacity .2s, filter .2s, scale .2s } [data-zustand=kopiert] .icon-kopie { opacity: 0; filter: blur(4px); scale: .6 }. Häkchen mit pathLength=\"1\" am Pfad: stroke-dasharray: 1; stroke-dashoffset: 1; im Zustand kopiert stroke-dashoffset: 0 mit 300 ms und 100 ms Verzögerung. Rückfall für alte Browser: execCommand('copy'), sonst Text markieren und Hinweis zeigen.",
   "mobil": "Identisch. Der Knopf braucht mindestens 44 px Zielfläche und darf nur als Icon erscheinen, wenn der Name für Screenreader bleibt.",
   "reduzierte_bewegung": "Nur Überblenden ohne Blur, Scale, Aufsteigen oder Rollen. Das Häkchen erscheint fertig gezeichnet.",
   "barrierefreiheit": "Statusmeldung per aria-live=\"polite\". Der Button-Name bleibt gleich („E-Mail-Adresse kopieren“), nur die sichtbare Bestätigung wechselt. Im Fehlerfall den Text markieren und den Hinweis vorlesen lassen."
  },
  "geprueft": "01.11.2026",
  "notiz": "Kontaktbereich der erfundenen Tischlerei Holm, Lüneburg, nach Rezept handwerk-werkstatt-klartext: Grund #EFEDEA, Salbei-Fläche mit eigener SVG-Werkzeichnung (Sideboard mit Maßketten, Detail Multiplex-Kante, Schriftfeld), ein Signalton #FB6100 nur für Anruf und Angebotsanfrage, Schriften Special Gothic (wdth 75–125) und Atkinson Hyperlegible Next. Drei Kopierziele: E-Mail für Anfragen, IBAN (kopiert ohne Leerzeichen), Werkstatt-Adresse mit Firmenname. Umschalter für drei Varianten und zwei gemessene Haltezeiten (2 s, 1 s). Echtes Kopieren mit Clipboard-API, Rückfall und Fehlerhinweis. Die Vorführung klickt ohne echte Zwischenablage. Bewegungswerte unverändert. Zugang 02.11.2026: Schriftfeld-Labels Alpha .6 → .72 (4,9:1 auf #bdc1a9). Text-Roll-Maske in lh statt em (Höhe 1lh, Rolle translate -1lh), wächst bei erhöhtem Zeilenabstand mit. Bis 360 px E-Mail 18,5 px und Adresse 16 px, damit nichts gekürzt wird. Kontrastmodus: Knöpfe mit Rahmen ButtonText."
 }
}
