|
| 1 | +import React, { useState } from "react"; |
| 2 | + |
| 3 | +/** |
| 4 | + * Props for the CopyCodeButton component. |
| 5 | + */ |
| 6 | +interface CopyCodeButtonProps { |
| 7 | + /** Code passed in so it can be copied */ |
| 8 | + code: string; |
| 9 | + /** To modify styling on the fly (so the component can be used anywhere)*/ |
| 10 | + className?: string; |
| 11 | +} |
| 12 | + |
| 13 | +/** |
| 14 | + * A reusable copy code button component with styling that can be modified. |
| 15 | + */ |
| 16 | +const CopyCodeButton: React.FC<CopyCodeButtonProps> = ({ |
| 17 | + code, |
| 18 | + className = "", |
| 19 | +}) => { |
| 20 | + const [copied, setCopied] = useState(false); |
| 21 | + |
| 22 | + const handleCopy = async () => { |
| 23 | + try { |
| 24 | + await navigator.clipboard.writeText(code); |
| 25 | + setCopied(true); |
| 26 | + setTimeout(() => setCopied(false), 3000); |
| 27 | + } catch (err) { |
| 28 | + console.error("Failed to copy code:", err); |
| 29 | + } |
| 30 | + }; |
| 31 | + |
| 32 | + return ( |
| 33 | + <div className="flex items-center"> |
| 34 | + <button |
| 35 | + onClick={handleCopy} |
| 36 | + className={`${className}`} |
| 37 | + title={copied ? "Copied!" : "Copy code"} |
| 38 | + aria-label={copied ? "Code copied to clipboard" : "Copy code to clipboard"} |
| 39 | + > |
| 40 | + {copied ? ( |
| 41 | + // https://heroicons.com/ |
| 42 | + <span> |
| 43 | + {/* Checkmark SVG icon */} |
| 44 | + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" className="size-5"> |
| 45 | + <path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5" /> |
| 46 | + </svg> |
| 47 | + </span> |
| 48 | + ) : ( |
| 49 | + <span> |
| 50 | + {/* Clipboard copy icon */} |
| 51 | + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" className="size-5"> |
| 52 | + <path stroke-linecap="round" stroke-linejoin="round" d="M8.25 7.5V6.108c0-1.135.845-2.098 1.976-2.192.373-.03.748-.057 1.123-.08M15.75 18H18a2.25 2.25 0 0 0 2.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48.424 48.424 0 0 0-1.123-.08M15.75 18.75v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5A3.375 3.375 0 0 0 6.375 7.5H5.25m11.9-3.664A2.251 2.251 0 0 0 15 2.25h-1.5a2.251 2.251 0 0 0-2.15 1.586m5.8 0c.065.21.1.433.1.664v.75h-6V4.5c0-.231.035-.454.1-.664M6.75 7.5H4.875c-.621 0-1.125.504-1.125 1.125v12c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V16.5a9 9 0 0 0-9-9Z" /> |
| 53 | + </svg> |
| 54 | + </span> |
| 55 | + )} |
| 56 | + </button> |
| 57 | + </div> |
| 58 | + ); |
| 59 | +}; |
| 60 | + |
| 61 | +export default CopyCodeButton; |
0 commit comments