Skip to content

Commit 9768947

Browse files
committed
Merge remote-tracking branch 'origin/master' into docs/enhance-node-requirements-state-management
2 parents 22abd1b + 1448c57 commit 9768947

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+267
-5012
lines changed

app/(home)/builderkit/page.tsx

Lines changed: 0 additions & 69 deletions
This file was deleted.

app/blog/page.tsx

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,21 +43,8 @@ export default function Page(): React.ReactElement {
4343
return (
4444
<>
4545
<HeroBackground />
46-
<main className="py-12 sm:py-20">
46+
<main className="relative py-12 sm:py-16">
4747
<div className="mx-auto max-w-7xl px-6 lg:px-8">
48-
{/* Header */}
49-
<section className="mx-auto w-full lg:mx-0 text-center">
50-
<h1 className="text-4xl sm:text-5xl font-bold tracking-tighter">
51-
<span className="bg-gradient-to-r from-slate-900 via-slate-700 to-slate-900 bg-clip-text text-transparent dark:from-white dark:via-slate-200 dark:to-white">
52-
Avalanche Builder Blog
53-
</span>
54-
</h1>
55-
<p className="mt-6 text-base sm:text-lg leading-7 text-muted-foreground">
56-
Takeaways and tutorials from building a network of fast,
57-
efficient, highly-optimized chains.
58-
</p>
59-
</section>
60-
6148
{/* Blog List with Search */}
6249
<BlogList blogs={blogs} />
6350
</div>

components/blog/blog-list.tsx

Lines changed: 124 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -25,24 +25,23 @@ interface BlogListProps {
2525
export function BlogList({ blogs }: BlogListProps) {
2626
const [filteredBlogs, setFilteredBlogs] = useState<BlogPost[]>(blogs);
2727
const handleFilteredResults = useCallback((filtered: BlogPost[]) => {setFilteredBlogs(filtered)}, []);
28-
const [featured, ...others] = filteredBlogs;
2928

3029
return (
3130
<>
32-
<section className="mt-8 sm:mt-12">
31+
<section className="mt-8 sm:mt-10">
3332
<BlogSearch blogs={blogs} onFilteredResults={handleFilteredResults} />
3433
</section>
3534

3635
{filteredBlogs.length !== blogs.length && (
37-
<section className="text-center mb-6">
36+
<section className="text-center mb-6 mt-6">
3837
<p className="text-sm text-muted-foreground">
3938
Showing {filteredBlogs.length} of {blogs.length} blog posts
4039
</p>
4140
</section>
4241
)}
4342

4443
{filteredBlogs.length === 0 && (
45-
<section className="text-center py-12">
44+
<section className="text-center py-16">
4645
<p className="text-lg text-muted-foreground mb-2">
4746
No matching blog posts found
4847
</p>
@@ -52,108 +51,140 @@ export function BlogList({ blogs }: BlogListProps) {
5251
</section>
5352
)}
5453

55-
{/* Featured Post */}
56-
{featured && (
57-
<section className="mt-6 sm:mt-8">
58-
<Link
59-
href={featured.url}
60-
className="group block overflow-hidden rounded-xl border border-white/20 bg-card/80 p-6 sm:p-8 shadow-sm transition duration-300 hover:border-[#E84142]/60 hover:shadow-[0_0_0_1px_rgba(232,65,66,0.6),0_0_30px_6px_rgba(232,65,66,0.35)] dark:bg-card-dark/80"
61-
>
62-
<div className="flex flex-col gap-4">
63-
<div className="flex items-center justify-between">
64-
<p className="text-xs text-muted-foreground">
65-
{new Date(
66-
featured.data.date ?? featured.url
67-
).toDateString()}
68-
</p>
69-
<span className="rounded-full bg-primary/10 px-3 py-1 text-xs font-medium text-primary">
70-
Featured
71-
</span>
72-
</div>
54+
{/* Blog Grid */}
55+
{filteredBlogs.length > 0 && (
56+
<section className="mt-10 sm:mt-12">
57+
{/* Featured Post - Full Width */}
58+
{filteredBlogs[0] && (
59+
<Link
60+
href={filteredBlogs[0].url}
61+
className="group relative flex flex-col md:flex-row gap-6 rounded-xl border border-primary/30 bg-gradient-to-br from-card/80 to-card/60 backdrop-blur-sm p-6 md:p-8 shadow-lg transition-all duration-300 hover:border-primary/50 hover:shadow-xl hover:shadow-primary/10 hover:-translate-y-0.5 dark:from-card-dark/80 dark:to-card-dark/60 dark:border-white/20 dark:hover:border-white/30 mb-8"
62+
>
63+
{/* Hover gradient overlay */}
64+
<div className="absolute inset-0 bg-gradient-to-br from-primary/5 to-transparent opacity-0 transition-opacity duration-300 group-hover:opacity-100 rounded-xl" />
7365

74-
<h2 className="text-2xl sm:text-3xl font-bold tracking-tight">
75-
{featured.data.title}
76-
</h2>
77-
78-
<p className="text-sm sm:text-base text-muted-foreground max-w-3xl">
79-
{featured.data.description}
80-
</p>
81-
82-
<div className="flex flex-wrap items-center gap-2 text-xs sm:text-sm">
83-
{featured.data.topics.map((topic: string) => (
84-
<span
85-
key={topic}
86-
className="rounded-full bg-fd-accent px-3 py-1.5 font-medium text-muted-foreground"
87-
>
88-
{topic}
66+
<div className="relative flex-1 flex flex-col">
67+
{/* Header */}
68+
<div className="flex items-center gap-3 mb-3">
69+
<span className="rounded-full bg-primary/15 px-3 py-1 text-xs font-semibold text-primary ring-1 ring-primary/20">
70+
Latest
8971
</span>
90-
))}
91-
</div>
72+
<time className="text-xs font-medium text-muted-foreground/70 uppercase tracking-wider">
73+
{new Date(filteredBlogs[0].data.date ?? filteredBlogs[0].url).toDateString()}
74+
</time>
75+
</div>
9276

93-
<div className="mt-2 flex flex-wrap items-center gap-3 text-sm text-muted-foreground">
94-
{featured.data.authors.map((author: string) => (
95-
<span key={author} className="inline-flex items-center gap-2">
96-
<X size={12} />
97-
<span className="truncate">{author}</span>
98-
</span>
99-
))}
100-
<span className="ml-auto inline-flex items-center gap-1 text-primary">
101-
Read article{" "}
102-
<ArrowRight
103-
size={14}
104-
className="transition-transform group-hover:translate-x-0.5"
105-
/>
106-
</span>
107-
</div>
108-
</div>
109-
</Link>
110-
</section>
111-
)}
77+
{/* Title */}
78+
<h3 className="text-2xl md:text-3xl font-bold tracking-tight leading-tight transition-colors group-hover:text-primary mb-3">
79+
{filteredBlogs[0].data.title}
80+
</h3>
11281

113-
{/* All Posts */}
114-
{others.length > 0 && (
115-
<section className="mt-12 sm:mt-16">
116-
<h3 className="mb-6 text-lg font-semibold tracking-tight text-foreground/90">
117-
{filteredBlogs.length === blogs.length
118-
? "Latest posts"
119-
: "More matching posts"}
120-
</h3>
121-
<div className="grid grid-cols-1 md:grid-cols-2 gap-5">
122-
{others.map((g) => (
123-
<Link
124-
key={g.url}
125-
href={g.url}
126-
className="flex flex-col gap-2 rounded-lg border border-white/20 bg-card p-4 shadow-sm transition duration-300 hover:border-[#E84142]/60 hover:shadow-[0_0_0_1px_rgba(232,65,66,0.6),0_0_24px_5px_rgba(232,65,66,0.3)] dark:bg-card-dark"
127-
>
128-
<p className="text-xs text-muted-foreground">
129-
{new Date(g.data.date ?? g.url).toDateString()}
130-
</p>
131-
<h4 className="text-xl font-semibold tracking-tight">
132-
{g.data.title}
133-
</h4>
134-
<p className="text-sm text-muted-foreground line-clamp-3">
135-
{g.data.description}
82+
{/* Description */}
83+
<p className="text-base text-muted-foreground/90 leading-relaxed mb-4 line-clamp-2">
84+
{filteredBlogs[0].data.description}
13685
</p>
137-
<div className="mt-2 flex flex-wrap items-center gap-2 text-xs">
138-
{g.data.topics.map((topic: string) => (
86+
87+
{/* Topics */}
88+
<div className="flex flex-wrap items-center gap-2 mb-4">
89+
{filteredBlogs[0].data.topics.slice(0, 4).map((topic: string) => (
13990
<span
14091
key={topic}
141-
className="rounded-full bg-fd-accent px-3 py-1.5 font-medium text-muted-foreground"
92+
className="rounded-full bg-secondary/70 px-3 py-1.5 text-xs font-medium text-foreground/80 transition-colors group-hover:bg-secondary"
14293
>
14394
{topic}
14495
</span>
14596
))}
97+
{filteredBlogs[0].data.topics.length > 4 && (
98+
<span className="text-xs text-muted-foreground">
99+
+{filteredBlogs[0].data.topics.length - 4}
100+
</span>
101+
)}
146102
</div>
147-
<div className="mt-1 flex flex-wrap items-center gap-2 text-sm text-muted-foreground">
148-
{g.data.authors.map((author: string) => (
149-
<span
150-
key={author}
151-
className="inline-flex items-center gap-2"
152-
>
153-
<X size={12} />
154-
<span className="truncate">{author}</span>
103+
104+
{/* Authors & Read More */}
105+
<div className="flex flex-wrap items-center justify-between gap-3 pt-3 mt-auto border-t border-border/30">
106+
<div className="flex flex-wrap items-center gap-3 text-sm text-muted-foreground/80">
107+
{filteredBlogs[0].data.authors.slice(0, 2).map((author: string) => (
108+
<span key={author} className="inline-flex items-center gap-1.5">
109+
<X size={12} />
110+
<span className="truncate font-medium text-xs">{author}</span>
111+
</span>
112+
))}
113+
{filteredBlogs[0].data.authors.length > 2 && (
114+
<span className="text-xs">+{filteredBlogs[0].data.authors.length - 2}</span>
115+
)}
116+
</div>
117+
<span className="inline-flex items-center gap-1.5 text-sm font-medium text-primary transition-transform group-hover:translate-x-1">
118+
Read article
119+
<ArrowRight size={16} className="transition-transform group-hover:translate-x-0.5" />
120+
</span>
121+
</div>
122+
</div>
123+
</Link>
124+
)}
125+
126+
{/* Regular Grid */}
127+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
128+
{filteredBlogs.slice(1).map((post) => (
129+
<Link
130+
key={post.url}
131+
href={post.url}
132+
className="group relative flex flex-col rounded-xl border border-border/50 bg-card/60 backdrop-blur-sm shadow-md transition-all duration-300 hover:border-primary/40 hover:shadow-xl hover:shadow-primary/10 hover:-translate-y-1 dark:bg-card-dark/60 dark:border-white/20 dark:hover:border-white/30 overflow-hidden"
133+
>
134+
{/* Hover gradient overlay */}
135+
<div className="absolute inset-0 bg-gradient-to-br from-primary/5 to-transparent opacity-0 transition-opacity duration-300 group-hover:opacity-100" />
136+
137+
<div className="relative flex flex-col h-full p-6">
138+
{/* Header */}
139+
<time className="text-xs font-medium text-muted-foreground/70 uppercase tracking-wider mb-3">
140+
{new Date(post.data.date ?? post.url).toDateString()}
141+
</time>
142+
143+
{/* Title */}
144+
<h4 className="text-xl font-bold tracking-tight leading-snug transition-colors group-hover:text-primary mb-3">
145+
{post.data.title}
146+
</h4>
147+
148+
{/* Description */}
149+
<p className="text-sm text-muted-foreground/90 leading-relaxed mb-4 flex-grow line-clamp-3">
150+
{post.data.description}
151+
</p>
152+
153+
{/* Topics */}
154+
<div className="flex flex-wrap items-center gap-2 mb-4">
155+
{post.data.topics.slice(0, 3).map((topic: string) => (
156+
<span
157+
key={topic}
158+
className="rounded-full bg-secondary/70 px-3 py-1.5 text-xs font-medium text-foreground/80 transition-colors group-hover:bg-secondary"
159+
>
160+
{topic}
161+
</span>
162+
))}
163+
{post.data.topics.length > 3 && (
164+
<span className="text-xs text-muted-foreground">
165+
+{post.data.topics.length - 3}
166+
</span>
167+
)}
168+
</div>
169+
170+
{/* Authors & Read More */}
171+
<div className="flex flex-wrap items-center justify-between gap-3 pt-3 border-t border-border/30">
172+
<div className="flex flex-wrap items-center gap-3 text-sm text-muted-foreground/80">
173+
{post.data.authors.slice(0, 2).map((author: string) => (
174+
<span key={author} className="inline-flex items-center gap-1.5">
175+
<X size={12} />
176+
<span className="truncate font-medium text-xs">{author}</span>
177+
</span>
178+
))}
179+
{post.data.authors.length > 2 && (
180+
<span className="text-xs">+{post.data.authors.length - 2}</span>
181+
)}
182+
</div>
183+
<span className="inline-flex items-center gap-1.5 text-xs font-medium text-primary transition-transform group-hover:translate-x-1">
184+
Read
185+
<ArrowRight size={14} className="transition-transform group-hover:translate-x-0.5" />
155186
</span>
156-
))}
187+
</div>
157188
</div>
158189
</Link>
159190
))}

components/blog/blog-search.tsx

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -45,22 +45,25 @@ export function BlogSearch({ blogs, onFilteredResults }: BlogSearchProps) {
4545
}, [filteredBlogs, onFilteredResults]);
4646

4747
return (
48-
<div className="relative w-full max-w-md mx-auto mb-8">
49-
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" />
50-
<Input
51-
placeholder="Search blogs by title, topic, author, or description..."
52-
value={searchQuery}
53-
onChange={(e) => setSearchQuery(e.target.value)}
54-
className="pl-10 pr-10 rounded-xl bg-white text-sm"
55-
/>
56-
{searchQuery && (
57-
<button
58-
onClick={() => setSearchQuery("")}
59-
className="absolute right-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground hover:text-foreground transition-colors"
60-
>
61-
<X className="h-4 w-4" />
62-
</button>
63-
)}
48+
<div className="relative w-full max-w-2xl mx-auto">
49+
<div className="relative">
50+
<Search className="absolute left-4 top-1/2 transform -translate-y-1/2 h-5 w-5 text-muted-foreground/60" />
51+
<Input
52+
placeholder="Search by title, topic, author, or description..."
53+
value={searchQuery}
54+
onChange={(e) => setSearchQuery(e.target.value)}
55+
className="pl-12 pr-12 py-6 rounded-xl bg-card/60 backdrop-blur-sm border-border/50 text-base shadow-lg transition-all duration-300 focus:shadow-xl focus:border-primary/30 focus:ring-2 focus:ring-primary/20"
56+
/>
57+
{searchQuery && (
58+
<button
59+
onClick={() => setSearchQuery("")}
60+
className="absolute right-4 top-1/2 transform -translate-y-1/2 h-5 w-5 text-muted-foreground/60 hover:text-foreground transition-colors"
61+
aria-label="Clear search"
62+
>
63+
<X className="h-5 w-5" />
64+
</button>
65+
)}
66+
</div>
6467
</div>
6568
);
6669
}

0 commit comments

Comments
 (0)