Skip to content

Commit d5246e2

Browse files
committed
Add install guide to freebuff landing page
1 parent 7b921d5 commit d5246e2

File tree

1 file changed

+89
-1
lines changed

1 file changed

+89
-1
lines changed

freebuff/web/src/app/home-client.tsx

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,85 @@ const faqs = [
3838
},
3939
]
4040

41+
const setupSteps = [
42+
{
43+
label: 'Open your terminal',
44+
description: 'Use any terminal — within VS Code, plain terminal, PowerShell, etc.',
45+
},
46+
{
47+
label: 'Navigate to your project',
48+
command: 'cd /path/to/your-repo',
49+
},
50+
{
51+
label: 'Install Freebuff',
52+
command: 'npm install -g freebuff',
53+
},
54+
{
55+
label: 'Run Freebuff',
56+
command: 'freebuff',
57+
},
58+
]
59+
60+
function SetupGuide() {
61+
const [isOpen, setIsOpen] = useState(false)
62+
63+
return (
64+
<div className="max-w-md mx-auto">
65+
<button
66+
onClick={() => setIsOpen(!isOpen)}
67+
aria-expanded={isOpen}
68+
className="flex items-center gap-2 mx-auto text-sm text-zinc-400 hover:text-acid-green transition-colors duration-200 cursor-pointer group"
69+
>
70+
<span>Install guide</span>
71+
<motion.span
72+
animate={{ rotate: isOpen ? 180 : 0 }}
73+
transition={{ duration: 0.25 }}
74+
>
75+
<ChevronDown className="h-3.5 w-3.5" />
76+
</motion.span>
77+
</button>
78+
79+
<AnimatePresence initial={false}>
80+
{isOpen && (
81+
<motion.div
82+
initial={{ height: 0, opacity: 0 }}
83+
animate={{ height: 'auto', opacity: 1 }}
84+
exit={{ height: 0, opacity: 0 }}
85+
transition={{ duration: 0.3, ease: 'easeInOut' }}
86+
className="overflow-hidden"
87+
>
88+
<div className="mt-4 bg-zinc-900/60 border border-zinc-800 rounded-xl p-5 text-left">
89+
<ol className="space-y-4">
90+
{setupSteps.map((step, i) => (
91+
<li key={i} className="flex gap-3">
92+
<span className="flex-shrink-0 w-6 h-6 rounded-full bg-acid-green/10 border border-acid-green/30 flex items-center justify-center text-xs font-mono text-acid-green">
93+
{i + 1}
94+
</span>
95+
<div className="flex-1 min-w-0">
96+
<p className="text-sm font-medium text-white/90">{step.label}</p>
97+
{'description' in step && step.description && (
98+
<p className="text-xs text-zinc-500 mt-0.5">{step.description}</p>
99+
)}
100+
{'command' in step && step.command && (
101+
<div className="mt-1.5 flex items-center gap-2 bg-zinc-800/60 border border-zinc-700/40 rounded-md px-3 py-1.5 hover:border-acid-green/30 transition-colors duration-200">
102+
<code className="font-mono text-xs text-white/80 flex-1 select-all">
103+
{step.command}
104+
</code>
105+
<CopyButton value={step.command} />
106+
</div>
107+
)}
108+
</div>
109+
</li>
110+
))}
111+
</ol>
112+
</div>
113+
</motion.div>
114+
)}
115+
</AnimatePresence>
116+
</div>
117+
)
118+
}
119+
41120
function InstallCommand({ className }: { className?: string }) {
42121
return (
43122
<div
@@ -180,10 +259,19 @@ export default function HomeClient() {
180259
initial={{ opacity: 0, y: 20 }}
181260
animate={{ opacity: 1, y: 0 }}
182261
transition={{ duration: 0.5, delay: 1.0 }}
183-
className="max-w-md mx-auto mb-8"
262+
className="max-w-md mx-auto mb-4"
184263
>
185264
<InstallCommand />
186265
</motion.div>
266+
267+
<motion.div
268+
initial={{ opacity: 0 }}
269+
animate={{ opacity: 1 }}
270+
transition={{ duration: 0.5, delay: 1.3 }}
271+
className="mb-8"
272+
>
273+
<SetupGuide />
274+
</motion.div>
187275
</div>
188276

189277
{/* Bottom fade */}

0 commit comments

Comments
 (0)