- Home hero: full-height, with an interactive 3D wireframe of my face (MediaPipe landmarks from my-photo.png) rendered as a network graph with packets, scan sweeps and an assemble-on-load entry animation - Inner pages: shared PageHero with a themed scene per page (About helix, Skills geodesic sphere, Work infra stack, Blog signal waves, Contact globe with connection arcs) - Shared Three.js stage (framing, GSAP entry, pointer, off-screen pausing, reduced motion) with lazily loaded per-scene chunks - GSAP motion system: data-reveal / data-reveal-stagger / data-parallax attributes, SplitText headings, divider draw-in, page exit fade, no-JS and reduced-motion fallbacks - Mobile: graphic stacks above the text Co-Authored-By: Claude Opus 5.5 <[email protected]>
39 lines
1.3 KiB
TypeScript
39 lines
1.3 KiB
TypeScript
import EmptyContent from "@/src/components/lib/elements/EmptyContent";
|
|
import Section from "@/src/components/lib/layout/Section";
|
|
import { AppContext } from "@/src/pages/__root";
|
|
import React from "react";
|
|
import BlogPostsListCard from "./BlogPostsListCard";
|
|
import Stack from "@/src/components/lib/layout/Stack";
|
|
import Divider from "@/src/components/lib/layout/Divider";
|
|
import LucideIcon from "@/src/components/lib/elements/lucide-icon";
|
|
|
|
export default function BlogPostsList() {
|
|
const { pageProps } = React.useContext(AppContext);
|
|
const { blogPosts } = pageProps || {};
|
|
|
|
if (!blogPosts?.[0]) {
|
|
return (
|
|
<>
|
|
<Divider />
|
|
<Section>
|
|
<EmptyContent
|
|
title={`No Blog Posts at this moment`}
|
|
borderProps={{ className: "p-10 xl:p-20" }}
|
|
icon={<LucideIcon name="NotebookPen" />}
|
|
/>
|
|
</Section>
|
|
</>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Section className="!mt-0 !pt-0">
|
|
<Stack className="w-full" data-reveal-stagger>
|
|
{blogPosts.map((post, index) => {
|
|
return <BlogPostsListCard post={post} key={index} />;
|
|
})}
|
|
</Stack>
|
|
</Section>
|
|
);
|
|
}
|