|
3 | 3 | import { VscVscode } from "react-icons/vsc" |
4 | 4 | import Link from "next/link" |
5 | 5 | import { motion } from "framer-motion" |
| 6 | +import { Copy, Check } from "lucide-react" |
| 7 | +import { useState } from "react" |
6 | 8 |
|
7 | 9 | interface InstallSectionProps { |
8 | 10 | downloads: string | null |
9 | 11 | } |
10 | 12 |
|
11 | 13 | export function InstallSection({ downloads }: InstallSectionProps) { |
| 14 | + const [copied, setCopied] = useState(false) |
| 15 | + const installCmd = "code --install-extension RooVeterinaryInc.roo-cline" |
| 16 | + |
| 17 | + const handleCopy = async () => { |
| 18 | + try { |
| 19 | + await navigator.clipboard.writeText(installCmd) |
| 20 | + setCopied(true) |
| 21 | + setTimeout(() => setCopied(false), 1000) |
| 22 | + } catch (_e) { |
| 23 | + // Fallback for environments without Clipboard API support |
| 24 | + const textarea = document.createElement("textarea") |
| 25 | + textarea.value = installCmd |
| 26 | + document.body.appendChild(textarea) |
| 27 | + textarea.select() |
| 28 | + try { |
| 29 | + document.execCommand("copy") |
| 30 | + setCopied(true) |
| 31 | + setTimeout(() => setCopied(false), 1000) |
| 32 | + } finally { |
| 33 | + document.body.removeChild(textarea) |
| 34 | + } |
| 35 | + } |
| 36 | + } |
| 37 | + |
12 | 38 | const backgroundVariants = { |
13 | 39 | hidden: { |
14 | 40 | opacity: 0, |
@@ -84,12 +110,27 @@ export function InstallSection({ downloads }: InstallSectionProps) { |
84 | 110 | <div className="absolute -inset-px rounded-xl bg-gradient-to-r from-blue-500/50 via-cyan-500/50 to-purple-500/50 opacity-30 blur-sm transition-all duration-500 group-hover:opacity-60 dark:opacity-40 dark:group-hover:opacity-70" /> |
85 | 111 | <div className="relative overflow-hidden rounded-xl border border-border bg-background/80 shadow-lg backdrop-blur-xl transition-all duration-500 ease-out group-hover:border-blue-500/50 group-hover:shadow-xl group-hover:shadow-blue-500/10 dark:border-border/50 dark:bg-background/60 dark:group-hover:border-blue-400/50"> |
86 | 112 | <div className="border-b border-border/50 bg-muted/30 px-4 py-3 dark:bg-muted/20"> |
87 | | - <div className="text-sm font-medium text-foreground">or via CLI</div> |
| 113 | + <div className="flex items-center justify-between"> |
| 114 | + <div className="text-sm font-medium text-foreground">or via CLI</div> |
| 115 | + <button |
| 116 | + type="button" |
| 117 | + onClick={handleCopy} |
| 118 | + className="inline-flex items-center gap-2 rounded-md px-2 py-1 text-xs font-medium text-foreground/80 hover:text-foreground hover:bg-foreground/5 transition-colors" |
| 119 | + aria-label={copied ? "Copied" : "Copy install command to clipboard"} |
| 120 | + title={copied ? "Copied!" : "Copy"}> |
| 121 | + {copied ? ( |
| 122 | + <Check className="h-4 w-4 text-green-500" /> |
| 123 | + ) : ( |
| 124 | + <Copy className="h-4 w-4" /> |
| 125 | + )} |
| 126 | + <span className="sr-only">{copied ? "Copied" : "Copy"}</span> |
| 127 | + </button> |
| 128 | + </div> |
88 | 129 | </div> |
89 | 130 | <div className="overflow-x-auto bg-background/50 dark:bg-background/30"> |
90 | 131 | <pre className="p-4"> |
91 | 132 | <code className="whitespace-pre-wrap break-all text-sm font-mono text-foreground sm:break-normal sm:text-base"> |
92 | | - code --install-extension RooVeterinaryInc.roo-cline |
| 133 | + {installCmd} |
93 | 134 | </code> |
94 | 135 | </pre> |
95 | 136 | </div> |
|
0 commit comments