Skip to content

Commit 87d3bc5

Browse files
committed
feat: installation scripts toggle on homepage
1 parent 2b31fdc commit 87d3bc5

4 files changed

Lines changed: 187 additions & 45 deletions

File tree

islands/InstallToggle.tsx

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
import { useState } from "preact/hooks";
2+
import { Copy, Download, Monitor, Terminal, Zap } from "lucide-preact";
3+
4+
interface Platform {
5+
id: string;
6+
name: string;
7+
icon: unknown;
8+
command: string;
9+
downloadUrl: string;
10+
color: string;
11+
}
12+
13+
const platforms: Platform[] = [
14+
{
15+
id: "bash",
16+
name: "Linux/macOS",
17+
icon: Terminal,
18+
command: "curl -fsSL https://tryandromeda.dev/install.sh | bash",
19+
downloadUrl: "/install.sh",
20+
color: "green",
21+
},
22+
{
23+
id: "powershell",
24+
name: "Windows (PowerShell)",
25+
icon: Monitor,
26+
command: `iwr -Uri "https://tryandromeda.dev/install.ps1" | Invoke-Expression`,
27+
downloadUrl: "/install.ps1",
28+
color: "blue",
29+
},
30+
{
31+
id: "cmd",
32+
name: "Windows (CMD)",
33+
icon: Zap,
34+
command: "curl -L -o install.bat https://tryandromeda.dev/install.bat && install.bat",
35+
downloadUrl: "/install.bat",
36+
color: "peach",
37+
},
38+
];
39+
40+
export default function InstallToggle() {
41+
const [selectedPlatform, setSelectedPlatform] = useState("bash");
42+
43+
const currentPlatform = platforms.find(p => p.id === selectedPlatform)!;
44+
45+
const copyToClipboard = async (text: string) => {
46+
try {
47+
await navigator.clipboard.writeText(text);
48+
// Could add toast notification here
49+
} catch (err) {
50+
console.error("Failed to copy:", err);
51+
}
52+
};
53+
54+
const downloadScript = () => {
55+
const link = document.createElement('a');
56+
link.href = currentPlatform.downloadUrl;
57+
link.download = currentPlatform.downloadUrl.split('/').pop() || 'install';
58+
document.body.appendChild(link);
59+
link.click();
60+
document.body.removeChild(link);
61+
};
62+
return (
63+
<div class="w-full max-w-4xl mx-auto"> {/* Container with consistent theme colors */}
64+
<div class="relative overflow-hidden bg-base border border-surface1 rounded-2xl shadow-lg"> {/* Header */}
65+
<div class="text-center p-6 sm:p-8 pb-4">
66+
<h3 class="text-xl sm:text-2xl font-bold mb-2 tracking-tight" style={{ color: 'var(--color-text)' }}>
67+
Quick Install
68+
</h3>
69+
<p class="text-sm sm:text-base font-medium" style={{ color: 'var(--color-subtext1)' }}>
70+
Choose your platform to get started
71+
</p>
72+
</div>{/* Platform Selection Grid - Smaller boxes */}
73+
<div class="px-4 sm:px-8 pb-6">
74+
<div class="grid grid-cols-1 sm:grid-cols-3 gap-3">{platforms.map((platform) => {
75+
// deno-lint-ignore no-explicit-any
76+
const IconComponent = platform.icon as any;
77+
const isSelected = selectedPlatform === platform.id;
78+
79+
return (
80+
<button
81+
key={platform.id}
82+
type="button"
83+
onClick={() => setSelectedPlatform(platform.id)} class={`group relative overflow-hidden p-4 rounded-lg border transition-all duration-300 transform ${
84+
isSelected
85+
? `bg-${platform.color} text-base border-${platform.color} shadow-lg scale-105`
86+
: "bg-surface0 hover:bg-surface1 border-surface1 hover:border-surface2 hover:scale-102 hover:shadow-md"
87+
}`}
88+
style={isSelected ? {
89+
backgroundColor: `var(--color-${platform.color})`,
90+
borderColor: `var(--color-${platform.color})`,
91+
color: 'var(--color-base)'
92+
} : {
93+
color: 'var(--color-text)'
94+
}}> {/* Icon */}
95+
<div class="flex justify-center mb-2">
96+
<div class={`p-2 rounded-lg transition-colors ${
97+
isSelected
98+
? "bg-base/20"
99+
: "bg-surface1 group-hover:bg-surface2"
100+
}`}> <IconComponent
101+
size={20}
102+
class={isSelected ? "text-base" : ""}
103+
style={isSelected ? { color: 'var(--color-base)' } : { color: 'var(--color-text)' }}
104+
/>
105+
</div>
106+
</div> {/* Platform name */}
107+
<div class="text-center"> <div
108+
class={`text-xs sm:text-sm font-semibold ${
109+
isSelected ? "text-base" : ""
110+
}`}
111+
style={isSelected ? { color: 'var(--color-base)' } : { color: 'var(--color-text)' }}
112+
>
113+
{platform.name}
114+
</div>
115+
</div>
116+
</button>
117+
);
118+
})}
119+
</div>
120+
</div>
121+
122+
{/* Command Section */}
123+
<div class="px-4 sm:px-8 pb-6 sm:pb-8"> <div class="bg-mantle rounded-xl border border-surface1 overflow-hidden">
124+
{/* Header with actions */}
125+
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 p-4 bg-surface0 border-b border-surface1"> <h4 class="text-sm sm:text-base font-semibold flex items-center gap-2" style={{ color: 'var(--color-text)' }}>
126+
<Terminal size={16} style={{ color: 'var(--color-subtext1)' }} />
127+
Installation Command
128+
</h4>
129+
<div class="flex gap-2"> <button
130+
type="button"
131+
onClick={downloadScript}
132+
class="flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-lg transition-all duration-200 hover:scale-105 shadow-md hover:shadow-lg"
133+
style={{
134+
backgroundColor: 'var(--color-yellow)',
135+
color: 'var(--color-base)'
136+
}}
137+
title="Download script"
138+
>
139+
<Download size={16} />
140+
<span class="hidden sm:inline">Download</span>
141+
</button> <button
142+
type="button"
143+
onClick={() => copyToClipboard(currentPlatform.command)}
144+
class="flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-lg transition-all duration-200 hover:scale-105 shadow-md hover:shadow-lg"
145+
style={{
146+
backgroundColor: 'var(--color-green)',
147+
color: 'var(--color-base)'
148+
}}
149+
title="Copy to clipboard"
150+
>
151+
<Copy size={16} />
152+
<span class="hidden sm:inline">Copy</span>
153+
</button>
154+
</div>
155+
</div>
156+
{/* Command display */}
157+
<div class="p-4">
158+
<pre class="text-sm sm:text-base font-mono leading-relaxed overflow-x-auto" style={{ color: 'var(--color-text)' }}>
159+
<code>{currentPlatform.command}</code>
160+
</pre>
161+
</div>
162+
</div>
163+
</div>
164+
165+
{/* Info note */}
166+
<div class="px-4 sm:px-8 pb-6 sm:pb-8">
167+
<div class="bg-surface0/50 rounded-lg border border-surface1/50 p-4"> <p class="text-xs sm:text-sm leading-relaxed" style={{ color: 'var(--color-subtext1)' }}>
168+
<span class="font-semibold" style={{ color: 'var(--color-text)' }}>Note:</span> These scripts automatically detect your platform, download the appropriate binary, and add it to your PATH.{" "}
169+
<span class="hidden sm:inline">You can also download and inspect the scripts before running them.</span>
170+
</p>
171+
</div>
172+
</div>
173+
</div>
174+
</div>
175+
);
176+
}

routes/docs/[...topic].tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,13 @@ import toc from "../../utils/toc.ts";
1111
export default async function DocTopic(props: PageProps) {
1212
const topic = props.params.topic;
1313
const content = await Deno.readTextFile(`static/content/docs/${topic}.md`)
14-
.then((
15-
res,
16-
) => res).catch((_e) => {
14+
.then((res) => res).catch((_e) => {
1715
console.error(_e);
1816
return `# 404 Not Found
1917
20-
The page you're looking for doesn't exist.
18+
The page you're looking for doesn't exist.
2119
22-
[← Back to Documentation](/docs)`;
20+
[← Back to Documentation](/docs)`;
2321
});
2422

2523
return (

routes/index.tsx

Lines changed: 3 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Target, Zap } from "lucide-preact";
22

33
import NavBar from "../components/NavBar.tsx";
44
import Footer from "../components/Footer.tsx";
5+
import InstallToggle from "../islands/InstallToggle.tsx";
56

67
export default function Home() {
78
return (
@@ -32,39 +33,8 @@ export default function Home() {
3233
</p>
3334

3435
{/* Install Command */}
35-
<div class="max-w-2xl mx-auto mb-8">
36-
<pre class="bg-black text-green-400 p-4 rounded-lg text-left overflow-x-auto border border-surface1">
37-
<code>cargo install --git https://github.com/tryandromeda/andromeda</code>
38-
</pre>
39-
{/* Quick Install Options */}
40-
<div class="mt-4 text-center">
41-
<p class="text-subtext1 text-sm mb-2">Or use our installation scripts:</p>
42-
<div class="flex justify-center gap-2 text-xs">
43-
<a
44-
href="/install.sh"
45-
class="text-blue hover:text-blue/80 transition-colors"
46-
download
47-
>
48-
Bash
49-
</a>
50-
<span class="text-subtext1"></span>
51-
<a
52-
href="/install.ps1"
53-
class="text-blue hover:text-blue/80 transition-colors"
54-
download
55-
>
56-
PowerShell
57-
</a>
58-
<span class="text-subtext1"></span>
59-
<a
60-
href="/install.bat"
61-
class="text-blue hover:text-blue/80 transition-colors"
62-
download
63-
>
64-
Batch
65-
</a>
66-
</div>
67-
</div>
36+
<div class="max-w-4xl mx-auto mb-8">
37+
<InstallToggle />
6838
</div>{" "}
6939
<div class="mt-8 flex flex-col sm:flex-row gap-4 justify-center">
7040
<a

static/content/docs/installation.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,13 @@ chmod +x install.sh
2828
### Windows (PowerShell)
2929

3030
```powershell
31-
iwr -Uri "https://tryandromeda.dev/install.ps1" -OutFile "install.ps1"
32-
.\install.ps1
31+
iwr -Uri "https://tryandromeda.dev/install.ps1" | Invoke-Expression
3332
```
3433

3534
### Windows (Command Prompt)
3635

3736
```cmd
38-
curl -L -o install.bat https://tryandromeda.dev/install.bat
39-
install.bat
37+
curl -L -o install.bat https://tryandromeda.dev/install.bat && install.bat
4038
```
4139

4240
## Other Installation Methods
@@ -159,18 +157,18 @@ andromeda completions powershell > andromeda.ps1
159157

160158
### Common Issues
161159

162-
_"andromeda: command not found"_*
160+
#### "andromeda: command not found"
163161

164162
- Ensure `~/.cargo/bin` is in your PATH
165163
- Restart your terminal after installation
166164

167-
**Build failures on installation**
165+
#### Build failures on installation
168166

169167
- Update Rust: `rustup update`
170168
- Clear Cargo cache: `cargo clean`
171169
- Try installing with `--force` flag
172170

173-
**Permission errors**
171+
#### Permission errors
174172

175173
- On Unix systems, ensure you have write permissions to `~/.cargo/bin`
176174
- On Windows, run as Administrator if needed

0 commit comments

Comments
 (0)