53 lines
1.4 KiB
TypeScript
53 lines
1.4 KiB
TypeScript
"use client";
|
|
|
|
import { BLOG_POSTS, type BlogPost } from "@/data/content";
|
|
import { useStaggerReveal } from "@/hooks/useAnimations";
|
|
import BlogPostCard from "@/components/BlogPostCard";
|
|
import "../styles/blog.css";
|
|
|
|
/** Sort posts newest-first by date (ISO display dates compare lexicographically). */
|
|
function sortPostsNewestFirst(posts: BlogPost[]): BlogPost[] {
|
|
return [...posts].sort((a, b) => b.date.localeCompare(a.date));
|
|
}
|
|
|
|
/** The blog tab: every post, newest first, in a single vertical stack. */
|
|
export default function BlogList() {
|
|
const posts = sortPostsNewestFirst(BLOG_POSTS);
|
|
const visible = useStaggerReveal(posts.length, 100);
|
|
|
|
return (
|
|
<div style={{ padding: "48px 0", minWidth: 0 }}>
|
|
<div
|
|
style={{
|
|
marginBottom: 8,
|
|
fontFamily: "var(--mono)",
|
|
fontSize: 11,
|
|
color: "var(--muted)",
|
|
letterSpacing: "0.08em",
|
|
textTransform: "uppercase",
|
|
}}
|
|
>
|
|
{"# blog"}
|
|
</div>
|
|
<h2
|
|
style={{
|
|
fontFamily: "var(--sans)",
|
|
fontSize: 28,
|
|
fontWeight: 700,
|
|
color: "var(--fg)",
|
|
margin: "0 0 32px 0",
|
|
letterSpacing: "-0.01em",
|
|
}}
|
|
>
|
|
{"Writing"}
|
|
</h2>
|
|
|
|
<div className="blog-list">
|
|
{posts.map((post, i) => (
|
|
<BlogPostCard key={post.id} post={post} visible={visible.has(i)} />
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|