Skip to content

Commit 9cbe6c3

Browse files
committed
feat: add CTA section, restyle interactive-grid atom
1 parent 8fa0356 commit 9cbe6c3

5 files changed

Lines changed: 59 additions & 34 deletions

File tree

src/routes/(app)/(home)/+page.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script lang="ts">
22
import { PKG_MANAGERS } from "$lib/constants/pkg-managers";
3-
import { About, Features, Hero, Showcase, Testimonials } from "$routes/(app)/(home)/components";
3+
import { About, Cta, Features, Hero, Showcase, Testimonials } from "$routes/(app)/(home)/components";
44
55
/** Set the active package manager tab */
66
let activeCmd = $derived(PKG_MANAGERS.find((p) => p.id === activeTab)?.cmd ?? "");
@@ -33,4 +33,5 @@
3333
<Features />
3434
<Showcase />
3535
<Testimonials />
36+
<Cta />
3637
</main>
Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,69 @@
11
<script lang="ts">
22
/** Props for the grid size */
33
let { size = 40 }: { size?: number } = $props();
4-
54
/** State for the number of columns and rows in the grid */
65
let columns = $state(0);
7-
86
/** State for the number of rows in the grid */
97
let rows = $state(0);
10-
118
/** State for the currently hovered cell */
129
let hoveredCell = $state<{ x: number; y: number } | null>(null);
13-
1410
/** Reference to the grid container */
1511
let container: HTMLElement;
16-
1712
/** Derived state for the row indices */
1813
let rowIndices = $derived(Array.from({ length: rows }, (_, i) => i));
19-
2014
/** Derived state for the column indices */
2115
let colIndices = $derived(Array.from({ length: columns }, (_, i) => i));
2216
2317
$effect(() => {
2418
if (!container) return;
25-
2619
const updateSize = () => {
2720
columns = Math.ceil(container.clientWidth / size);
2821
rows = Math.ceil(container.clientHeight / size);
2922
};
30-
3123
const handleMouseMove = (e: MouseEvent) => {
3224
if (!container) return;
33-
3425
const rect = container.getBoundingClientRect();
35-
3626
if (e.clientX < rect.left || e.clientX > rect.right || e.clientY < rect.top || e.clientY > rect.bottom) {
3727
hoveredCell = null;
3828
return;
3929
}
40-
4130
const cellX = Math.floor((e.clientX - rect.left) / size);
4231
const cellY = Math.floor((e.clientY - rect.top) / size);
43-
4432
if (hoveredCell?.x === cellX && hoveredCell?.y === cellY) return;
45-
4633
hoveredCell = { x: cellX, y: cellY };
4734
};
48-
4935
updateSize();
5036
window.addEventListener("resize", updateSize);
5137
window.addEventListener("mousemove", handleMouseMove);
52-
5338
return () => {
5439
window.removeEventListener("resize", updateSize);
5540
window.removeEventListener("mousemove", handleMouseMove);
5641
};
5742
});
5843
</script>
5944

60-
<figure
61-
bind:this={container}
62-
aria-hidden="true"
63-
class="pointer-events-none absolute inset-0 z-0 overflow-hidden mask-[linear-gradient(to_bottom,transparent_0%,black_10%,black_90%,transparent_100%)]"
64-
style="display: grid; grid-template-columns: repeat({columns}, {size}px); grid-template-rows: repeat({rows}, {size}px);"
65-
>
66-
{#each rowIndices as r (r)}
67-
{#each colIndices as c (c)}
68-
{@const isHovered = hoveredCell && Math.abs(hoveredCell.x - c) <= 1 && Math.abs(hoveredCell.y - r) <= 1}
69-
<div
70-
class="border-r border-b border-neutral-200/60 transition-colors {isHovered
71-
? 'bg-neutral-800/15 duration-75'
72-
: 'bg-transparent duration-500'}"
73-
></div>
45+
<div bind:this={container} class="pointer-events-none absolute inset-0 z-0 overflow-hidden bg-blue-600">
46+
<div
47+
class="absolute inset-0"
48+
style="background-image:
49+
radial-gradient(ellipse 75% 65% at 50% 0%, white 0%, white 70%, rgb(255 255 255 / 0) 80%),
50+
radial-gradient(ellipse 75% 65% at 50% 100%, white 0%, white 70%, rgb(255 255 255 / 0) 80%);"
51+
></div>
52+
53+
<figure
54+
aria-hidden="true"
55+
class="pointer-events-none absolute inset-0 z-0 overflow-hidden mask-[linear-gradient(to_bottom,transparent_0%,black_10%,black_90%,transparent_100%)]"
56+
style="display: grid; grid-template-columns: repeat({columns}, {size}px); grid-template-rows: repeat({rows}, {size}px);"
57+
>
58+
{#each rowIndices as r (r)}
59+
{#each colIndices as c (c)}
60+
{@const isHovered = hoveredCell && Math.abs(hoveredCell.x - c) <= 1 && Math.abs(hoveredCell.y - r) <= 1}
61+
<div
62+
class="border-r border-b border-white/20 transition-colors {isHovered
63+
? 'bg-white/15 duration-75'
64+
: 'bg-transparent duration-500'}"
65+
></div>
66+
{/each}
7467
{/each}
75-
{/each}
76-
</figure>
68+
</figure>
69+
</div>

src/routes/(app)/(home)/components/about.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
let subMetrics = $derived(metrics.filter((m) => m.position !== "featured"));
1717
</script>
1818

19-
<section class="relative w-full scroll-mt-28 bg-[#fbfbfb] px-6 py-16">
19+
<section class="relative w-full scroll-mt-28 bg-white px-6 py-16">
2020
<!-- <InteractiveGrid /> -->
2121
<div class="relative z-10 mx-auto flex max-w-7xl flex-col gap-16">
2222
<header class="grid grid-cols-1 items-start gap-8 lg:grid-cols-12 lg:gap-16">
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<script lang="ts">
2+
import { Github01Icon } from "@hugeicons/core-free-icons";
3+
import { HugeiconsIcon } from "@hugeicons/svelte";
4+
import { Button } from "$lib/components/button";
5+
import { InteractiveGrid } from "$routes/(app)/(home)/atoms";
6+
import { ROUTES } from "$lib/constants/routes";
7+
</script>
8+
9+
<section class="relative w-full scroll-mt-28 overflow-hidden bg-white px-6 py-20 sm:py-24">
10+
<InteractiveGrid />
11+
<div class="relative z-10 mx-auto flex max-w-7xl flex-col items-center gap-5 text-center">
12+
<h2
13+
class="text-black-950 max-w-2xl font-sans text-3xl font-bold tracking-tight text-balance sm:text-4xl md:text-[44px] md:leading-tight"
14+
>
15+
Zaman sekarang masih nulis component dari nol?
16+
</h2>
17+
<p class="text-black-600 max-w-xl font-sans text-base leading-relaxed font-normal md:text-[17px]">
18+
Copy perintahnya, paste di terminal, langsung pakai. Nggak ada setup ribet, nggak ada konfigurasi panjang.
19+
</p>
20+
<div class="mt-2 flex flex-col items-center gap-3 sm:flex-row sm:gap-4">
21+
<Button
22+
href={ROUTES.DOCS}
23+
class="flex cursor-pointer items-center gap-2 rounded-lg border-none bg-blue-600 px-6 py-3 text-sm font-medium text-white shadow-[0_1px_0_rgba(255,255,255,0.2)_inset,0_8px_20px_rgba(37,99,235,0.35)] transition-all duration-200 hover:bg-blue-700 hover:shadow-[0_1px_0_rgba(255,255,255,0.2)_inset,0_12px_24px_rgba(37,99,235,0.4)] active:scale-95 sm:px-7 sm:py-3.5 sm:text-[15px]"
24+
>
25+
<span>Star on GitHub</span>
26+
<HugeiconsIcon icon={Github01Icon} size={16} color="currentColor" />
27+
</Button>
28+
</div>
29+
</div>
30+
</section>
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import About from "$routes/(app)/(home)/components/about.svelte";
2+
import Cta from "$routes/(app)/(home)/components/cta.svelte";
23
import Features from "$routes/(app)/(home)/components/features.svelte";
34
import Hero from "$routes/(app)/(home)/components/hero.svelte";
45
import Showcase from "$routes/(app)/(home)/components/showcase.svelte";
56
import Testimonials from "$routes/(app)/(home)/components/testimonials.svelte";
67

7-
export { About, Features, Hero, Showcase, Testimonials };
8+
export { About, Cta, Features, Hero, Showcase, Testimonials };

0 commit comments

Comments
 (0)