Skip to content
File

Blob: src/client/islands/repo-admin/JsonResult.tsx

typescript39 lines
1import { useState } from "react";
2import { Check, Clipboard } from "lucide-react";
3 
4export function JsonResult({ data }: { data: unknown }) {
5 const [copied, setCopied] = useState(false);
6 const serialized = JSON.stringify(data, null, 2);
7 
8 async function copyJson() {
9 try {
10 await navigator.clipboard.writeText(serialized);
11 setCopied(true);
12 window.setTimeout(() => setCopied(false), 1200);
13 } catch (error) {
14 window.alert(`Failed to copy JSON: ${String(error)}`);
15 }
16 }
17 
18 return (
19 <div className="relative mt-2">
20 <pre className="overflow-x-auto rounded-xl bg-zinc-100 p-4 pr-12 text-sm dark:bg-zinc-800">
21 {serialized}
22 </pre>
23 <button
24 type="button"
25 onClick={() => void copyJson()}
26 className="absolute right-2 top-2 rounded border border-zinc-300 bg-white/80 p-1.5 text-zinc-600 transition-colors hover:bg-zinc-100 hover:text-zinc-900 dark:border-zinc-700 dark:bg-zinc-900/60 dark:text-zinc-300 dark:hover:bg-zinc-800 dark:hover:text-zinc-100"
27 title={copied ? "Copied" : "Copy JSON"}
28 aria-label="Copy JSON"
29 >
30 {copied ? (
31 <Check className="block h-4 w-4 text-green-600 dark:text-green-400" aria-hidden="true" />
32 ) : (
33 <Clipboard className="block h-4 w-4" aria-hidden="true" />
34 )}
35 </button>
36 </div>
37 );
38}