Skip to content

Commit 82200d5

Browse files
committed
feat(docs): add interactive Why section on home page
1 parent d2e2c70 commit 82200d5

File tree

1 file changed

+249
-29
lines changed

1 file changed

+249
-29
lines changed

docs/app/(home)/page.tsx

Lines changed: 249 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
/** biome-ignore-all lint/suspicious/noArrayIndexKey: Would need to look into this trivial issue */
22
"use client";
33

4+
import { CodeBlock } from "fumadocs-ui/components/codeblock";
45
import defaultMdxComponents from "fumadocs-ui/mdx";
56
import { cn } from "fumadocs-ui/utils/cn";
67
import {
78
BlocksIcon,
89
GitMergeIcon,
910
HomeIcon,
1011
SailboatIcon,
12+
TerminalIcon,
13+
Trash2Icon,
1114
ZapIcon,
1215
} from "lucide-react";
1316
import Image from "next/image";
1417
import Link from "next/link";
15-
import { useState } from "react";
18+
import { type HTMLProps, type ReactNode, useState } from "react";
19+
import { Pre } from "@/components/codeblock";
1620
import { buttonVariants } from "@/components/ui/button";
1721
import CkanDevstallerDemo from "./ckan-devstaller-demo.gif";
1822

@@ -37,6 +41,7 @@ export default function HomePage() {
3741
>
3842
<div className="relative mb-4">
3943
<Hero />
44+
<Why />
4045
</div>
4146
</div>
4247
<hr className="mt-12 mb-4" />
@@ -48,10 +53,20 @@ export default function HomePage() {
4853
href="https://dathere.com"
4954
target="_blank"
5055
className="font-medium text-blue-400"
56+
rel="noopener"
5157
>
5258
datHere
5359
</a>
54-
. <a href="https://dathere.com/privacy-policy/" target="_blank" className="font-medium text-blue-400">Privacy Policy</a>.
60+
.{" "}
61+
<a
62+
href="https://dathere.com/privacy-policy/"
63+
target="_blank"
64+
className="font-medium text-blue-400"
65+
rel="noopener"
66+
>
67+
Privacy Policy
68+
</a>
69+
.
5570
</p>
5671
</footer>
5772
</main>
@@ -123,33 +138,28 @@ function Hero() {
123138
Source Code
124139
</Link>
125140
</div>
126-
<Cards>
127-
<Card
128-
icon={<ZapIcon />}
129-
href="/docs"
130-
title="Quick start"
131-
>
132-
Get started with ckan-devstaller and install CKAN within minutes
133-
</Card>
134-
<Card icon={<BlocksIcon />} href="/docs/builder" title="Builder">
135-
Customize your installation with an interactive web GUI
136-
</Card>
137-
<Card
138-
icon={<HomeIcon />}
139-
href="/docs/reference/installation-architecture"
140-
title="Installation architecture"
141-
>
142-
Learn about where files are installed after running
143-
ckan-devstaller
144-
</Card>
145-
<Card
146-
icon={<GitMergeIcon />}
147-
href="https://github.com/dathere/ckan-devstaller"
148-
title="Source code"
149-
>
150-
View the source code of ckan-devstaller on GitHub
151-
</Card>
152-
</Cards>
141+
<Cards>
142+
<Card icon={<ZapIcon />} href="/docs" title="Quick start">
143+
Get started with ckan-devstaller and install CKAN within minutes
144+
</Card>
145+
<Card icon={<BlocksIcon />} href="/docs/builder" title="Builder">
146+
Customize your installation with an interactive web GUI
147+
</Card>
148+
<Card
149+
icon={<HomeIcon />}
150+
href="/docs/reference/installation-architecture"
151+
title="Installation architecture"
152+
>
153+
Learn about where files are installed after running ckan-devstaller
154+
</Card>
155+
<Card
156+
icon={<GitMergeIcon />}
157+
href="https://github.com/dathere/ckan-devstaller"
158+
title="Source code"
159+
>
160+
View the source code of ckan-devstaller on GitHub
161+
</Card>
162+
</Cards>
153163
<PreviewImages />
154164
</div>
155165
);
@@ -199,3 +209,213 @@ function PreviewImages() {
199209
</div>
200210
);
201211
}
212+
213+
function Why() {
214+
return (
215+
<div className="relative overflow-hidden border-x border-t p-2">
216+
<WhyInteractive
217+
codeblockInstall={
218+
<CodeBlock lang="bash">
219+
<Pre className="text-wrap pl-4">./ckan-devstaller</Pre>
220+
</CodeBlock>
221+
}
222+
codeblockUninstall={
223+
<CodeBlock lang="bash">
224+
<Pre className="text-wrap pl-4">./ckan-devstaller uninstall</Pre>
225+
</CodeBlock>
226+
}
227+
/>
228+
</div>
229+
);
230+
}
231+
232+
export function WhyInteractive(props: {
233+
codeblockInstall: ReactNode;
234+
codeblockUninstall: ReactNode;
235+
}) {
236+
const [active, setActive] = useState(0);
237+
const items = [
238+
[
239+
<ZapIcon className="w-4 h-4 inline-block" key={0} />,
240+
"Install CKAN within minutes",
241+
],
242+
[
243+
<BlocksIcon className="w-4 h-4 inline-block" key={1} />,
244+
"Customize your installation",
245+
],
246+
[
247+
<TerminalIcon className="w-4 h-4 inline-block" key={2} />,
248+
"Designed for developers",
249+
],
250+
[
251+
<Trash2Icon className="w-4 h-4 inline-block" key={3} />,
252+
"Uninstall with ease",
253+
],
254+
];
255+
256+
return (
257+
<div
258+
id="why-interactive"
259+
className="flex flex-col-reverse gap-3 md:flex-row md:min-h-[200px]"
260+
>
261+
<div className="flex flex-col">
262+
{items.map((item, i) => (
263+
<button
264+
key={item[1] as string}
265+
ref={(element) => {
266+
if (!element || i !== active) return;
267+
}}
268+
type="button"
269+
className={cn(
270+
"transition-colors text-nowrap border border-transparent rounded-lg px-3 py-2.5 text-start text-sm text-fd-muted-foreground font-medium",
271+
i === active
272+
? "text-fd-primary bg-fd-primary/10 border-fd-primary/10"
273+
: "hover:text-fd-accent-foreground/80 cursor-pointer",
274+
)}
275+
onClick={() => {
276+
setActive(i);
277+
}}
278+
>
279+
{item[0]} {item[1]}
280+
</button>
281+
))}
282+
</div>
283+
<style>
284+
{`
285+
@keyframes why-interactive-x {
286+
from {
287+
width: 0px;
288+
}
289+
290+
to {
291+
width: 100%;
292+
}
293+
}`}
294+
</style>
295+
296+
<div className="flex-1 p-4 border border-fd-primary/10 bg-fd-card/40 rounded-lg shadow-lg">
297+
{active === 0 ? (
298+
<WhyPanel>
299+
<h3>
300+
<ZapIcon className="w-4 h-4 inline-block mr-1 mb-1" />
301+
Install CKAN within minutes.
302+
</h3>
303+
<p>
304+
One of the primary goals of ckan-devstaller is to ease
305+
installation of CKAN for development. Built with Rust for speed
306+
and streamlining installation with{" "}
307+
<a href="https://github.com/tino097/ckan-compose/tree/ckan-devstaller">
308+
ckan-compose
309+
</a>
310+
, ckan-devstaller improves installation speeds{" "}
311+
<strong>from hours/days to just minutes</strong> depending on your
312+
download speed.
313+
</p>
314+
<div className="flex gap-2">
315+
<Link href="/docs" className={cn(buttonVariants(), "not-prose")}>
316+
Get started
317+
</Link>
318+
<Link
319+
href="/docs/builder"
320+
className={cn(buttonVariants(), "not-prose")}
321+
>
322+
Customize your installation
323+
</Link>
324+
</div>
325+
</WhyPanel>
326+
) : null}
327+
{active === 1 ? (
328+
<WhyPanel>
329+
<h3>
330+
<BlocksIcon className="w-4 h-4 inline-block mr-1 mb-1" />
331+
Customize your installation with the Builder.
332+
</h3>
333+
<p>
334+
Try out the interactive web GUI for customizing your CKAN
335+
installation. You can select:
336+
</p>
337+
<ul>
338+
<li>Presets</li>
339+
<li>CKAN version</li>
340+
<li>Extensions</li>
341+
<li>Features</li>
342+
</ul>
343+
<p>
344+
Then you can copy the provided ckan-devstaller command to run your
345+
selected configuration.
346+
</p>
347+
<div className="mt-4 flex flex-row items-center gap-1.5 not-prose">
348+
<Link href="/docs/builder" className={cn(buttonVariants())}>
349+
Try out the Builder
350+
</Link>
351+
</div>
352+
</WhyPanel>
353+
) : null}
354+
{active === 2 ? (
355+
<WhyPanel>
356+
<h3>
357+
<TerminalIcon className="w-4 h-4 inline-block mr-1 mb-1" />
358+
Designed for developers.
359+
</h3>
360+
<p>
361+
We've kept development use cases in mind while developing
362+
ckan-devstaller, such as:
363+
</p>
364+
<ul>
365+
<li>Trying out a new version of CKAN</li>
366+
<li>Developing CKAN extensions and themes</li>
367+
</ul>
368+
<div className="flex gap-2">
369+
<Link
370+
href="/docs/reference/installation-architecture"
371+
className={cn(buttonVariants(), "not-prose")}
372+
>
373+
View the installation architecture
374+
</Link>
375+
<Link
376+
href="https://github.com/dathere/ckan-devstaller"
377+
className={cn(buttonVariants({ variant: "ghost" }))}
378+
>
379+
Source code
380+
</Link>
381+
</div>
382+
</WhyPanel>
383+
) : null}
384+
{active === 3 ? (
385+
<WhyPanel>
386+
<h3>
387+
<Trash2Icon className="w-4 h-4 inline-block mr-1 mb-1" />
388+
Uninstall CKAN with ease.
389+
</h3>
390+
<p>
391+
After you've installed CKAN with ckan-devstaller, you can
392+
uninstall CKAN with ease. This allows for quickly re-installing
393+
CKAN for a different use case.
394+
</p>
395+
{props.codeblockUninstall}
396+
<Link
397+
href="/docs/tutorials/uninstall-ckan"
398+
className={cn(buttonVariants(), "not-prose")}
399+
>
400+
Learn more about uninstalling
401+
</Link>
402+
</WhyPanel>
403+
) : null}
404+
</div>
405+
</div>
406+
);
407+
}
408+
409+
function WhyPanel(props: HTMLProps<HTMLDivElement>) {
410+
return (
411+
<div
412+
{...props}
413+
className={cn(
414+
"duration-700 animate-in fade-in text-sm prose",
415+
props.className,
416+
)}
417+
>
418+
{props.children}
419+
</div>
420+
);
421+
}

0 commit comments

Comments
 (0)