feat(ui): Formular-Karten, Backup-Codes als Kacheln, Gutschein zum Kopieren
- Gemeinsame FormPanel-Karte fuer Passwort- und Zwei-Faktor-Seiten - Zwei-Faktor-Code: grosses, zentriertes Ziffernfeld - Backup-Codes als nummerierte Kacheln statt langer Liste - Newsletter-Bestaetigung: Willkommensrabatt als Gutschein mit gestricheltem Rand und Kopier-Knopf (bestaetigt "Kopiert") Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
76be1292ed
commit
ee854bd77b
12 files changed
+130
-23
No files matched your search
@@ -0,0 +1,55 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { AnimatePresence, motion } from "motion/react";
|
||||
|
||||
/**
|
||||
* Kopiert einen Gutscheincode in die Zwischenablage und bestaetigt das kurz
|
||||
* am Knopf selbst. Ohne Clipboard-API (aeltere Browser, unsicherer Kontext)
|
||||
* bleibt der Code sichtbar und markierbar — der Knopf meldet dann nichts.
|
||||
*/
|
||||
export function CopyCodeButton({ code, label, copiedLabel }: { code: string; label: string; copiedLabel: string }) {
|
||||
const [copied, setCopied] = useState(false);
|
||||
|
||||
async function copy() {
|
||||
try {
|
||||
await navigator.clipboard.writeText(code);
|
||||
setCopied(true);
|
||||
window.setTimeout(() => setCopied(false), 2000);
|
||||
} catch {
|
||||
// Kein Zugriff auf die Zwischenablage — der Code bleibt zum Markieren sichtbar.
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
onClick={copy}
|
||||
className="inline-flex h-10 items-center gap-2 border border-forest px-4 text-xs tracking-wide-caps text-forest transition-colors hover:bg-forest hover:text-cream"
|
||||
aria-live="polite"
|
||||
>
|
||||
<AnimatePresence mode="wait" initial={false}>
|
||||
<motion.span
|
||||
key={copied ? "done" : "idle"}
|
||||
initial={{ opacity: 0, y: 5 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -5 }}
|
||||
transition={{ duration: 0.15 }}
|
||||
className="inline-flex items-center gap-2"
|
||||
>
|
||||
<svg viewBox="0 0 24 24" className="h-3.5 w-3.5" fill="none" stroke="currentColor" strokeWidth="1.6" aria-hidden="true">
|
||||
{copied ? (
|
||||
<path d="M5 12.5l4.5 4.5L19 7.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
) : (
|
||||
<>
|
||||
<rect x="8" y="8" width="12" height="12" rx="1.5" />
|
||||
<path d="M16 8V5.5A1.5 1.5 0 0 0 14.5 4h-9A1.5 1.5 0 0 0 4 5.5v9A1.5 1.5 0 0 0 5.5 16H8" />
|
||||
</>
|
||||
)}
|
||||
</svg>
|
||||
{copied ? copiedLabel : label}
|
||||
</motion.span>
|
||||
</AnimatePresence>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user