| 1 |
"use client"; |
| 2 |
|
| 3 |
import { useState } from "react"; |
| 4 |
import ShellHighlighter from "./ShellHighlighter"; |
| 5 |
|
| 6 |
type TabKey = "curl" | "homebrew" | "source"; |
| 7 |
|
| 8 |
const installCommands: Record<TabKey, { label: string; commands: string[] }> = { |
| 9 |
curl: { |
| 10 |
label: "curl", |
| 11 |
commands: ["curl -fsSL https://tarmac.musicsian.com/install.sh | bash"], |
| 12 |
}, |
| 13 |
homebrew: { |
| 14 |
label: "Homebrew", |
| 15 |
commands: [ |
| 16 |
"brew tap gardesk/tap", |
| 17 |
"brew install ers", |
| 18 |
"brew install tarmac", |
| 19 |
], |
| 20 |
}, |
| 21 |
source: { |
| 22 |
label: "Source", |
| 23 |
commands: [ |
| 24 |
"git clone https://github.com/gardesk/tarmac.git", |
| 25 |
"cd tarmac && cargo build --release", |
| 26 |
"# binary at ./target/release/tarmac", |
| 27 |
], |
| 28 |
}, |
| 29 |
}; |
| 30 |
|
| 31 |
export default function Terminal() { |
| 32 |
const [activeTab, setActiveTab] = useState<TabKey>("curl"); |
| 33 |
const [copied, setCopied] = useState(false); |
| 34 |
|
| 35 |
const copyToClipboard = () => { |
| 36 |
const commands = installCommands[activeTab].commands |
| 37 |
.filter((cmd) => !cmd.startsWith("#")) |
| 38 |
.join("\n"); |
| 39 |
navigator.clipboard.writeText(commands); |
| 40 |
setCopied(true); |
| 41 |
setTimeout(() => setCopied(false), 2000); |
| 42 |
}; |
| 43 |
|
| 44 |
return ( |
| 45 |
<div className="terminal text-left max-w-2xl mx-auto"> |
| 46 |
<div className="terminal-header"> |
| 47 |
<div className="flex gap-1.5"> |
| 48 |
<span className="terminal-dot bg-red-500" /> |
| 49 |
<span className="terminal-dot bg-yellow-500" /> |
| 50 |
<span className="terminal-dot bg-green-500" /> |
| 51 |
</div> |
| 52 |
<div className="flex-1 flex gap-1 ml-4 overflow-x-auto"> |
| 53 |
{(Object.keys(installCommands) as TabKey[]).map((key) => ( |
| 54 |
<button |
| 55 |
key={key} |
| 56 |
onClick={() => setActiveTab(key)} |
| 57 |
className={`px-3 py-1 text-xs rounded transition-colors ${ |
| 58 |
activeTab === key |
| 59 |
? "bg-surface-700 text-surface-100" |
| 60 |
: "text-surface-400 hover:text-surface-200 hover:bg-surface-800" |
| 61 |
}`} |
| 62 |
> |
| 63 |
{installCommands[key].label} |
| 64 |
</button> |
| 65 |
))} |
| 66 |
</div> |
| 67 |
<button |
| 68 |
onClick={copyToClipboard} |
| 69 |
className="text-surface-400 hover:text-surface-200 text-xs px-2" |
| 70 |
title="Copy to clipboard" |
| 71 |
> |
| 72 |
{copied ? "Copied" : "Copy"} |
| 73 |
</button> |
| 74 |
</div> |
| 75 |
|
| 76 |
<div className="terminal-content"> |
| 77 |
{installCommands[activeTab].commands.map((cmd, i) => ( |
| 78 |
<div key={i} className="flex"> |
| 79 |
{!cmd.startsWith("#") && ( |
| 80 |
<span className="text-green-500 mr-2 select-none">$</span> |
| 81 |
)} |
| 82 |
<ShellHighlighter code={cmd} /> |
| 83 |
</div> |
| 84 |
))} |
| 85 |
</div> |
| 86 |
</div> |
| 87 |
); |
| 88 |
} |