mirror of
https://github.com/Since-3/since3-portal.git
synced 2026-10-12 21:41:16 +00:00
51 lines
1.7 KiB
TypeScript
51 lines
1.7 KiB
TypeScript
"use client"
|
|
|
|
import { useRef, useState } from "react";
|
|
import { CheckIcon, CopyIcon } from "lucide-react";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Input } from "@/components/ui/input";
|
|
import { Field, FieldLabel } from "@/components/ui/field";
|
|
|
|
export function CopyField({ label, value }: { label: string; value: string }) {
|
|
const [status, setStatus] = useState<"idle" | "copied" | "error">("idle");
|
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
|
|
async function handleCopy() {
|
|
try {
|
|
await navigator.clipboard.writeText(value);
|
|
setStatus("copied");
|
|
} catch {
|
|
inputRef.current?.select();
|
|
setStatus("error");
|
|
}
|
|
setTimeout(() => setStatus("idle"), 1500);
|
|
}
|
|
|
|
return (
|
|
<Field>
|
|
<FieldLabel>{label}</FieldLabel>
|
|
<div className="flex items-center gap-2">
|
|
<Input ref={inputRef} value={value} readOnly className="focus-visible:ring-0" />
|
|
<Button
|
|
type="button"
|
|
variant="outline"
|
|
size="icon"
|
|
className="shrink-0 cursor-pointer"
|
|
onClick={handleCopy}
|
|
aria-label={`${label} kopieren`}
|
|
>
|
|
{status === "copied" ? (
|
|
<CheckIcon className="text-signal-success" />
|
|
) : (
|
|
<CopyIcon />
|
|
)}
|
|
</Button>
|
|
</div>
|
|
{status === "error" && (
|
|
<p className="text-small text-destructive">
|
|
Kopieren fehlgeschlagen — Text wurde markiert, bitte manuell kopieren.
|
|
</p>
|
|
)}
|
|
</Field>
|
|
)
|
|
}
|