Files
dalcode-website/components/BlogCard.tsx
T
Leon-in 95eb362bfc feat: initial commit — Webflow to Next.js conversion
QuantumLab template converted to Next.js 16 + React 19 + TypeScript:
- 8 page routes (home, about, blog, contact, careers, team-members, coming-soon, 404)
- Dynamic routes for blog posts, career positions, and team members
- GSAP animations (marquee, counters, button hovers)
- IntersectionObserver-based scroll reveal (blur-to-clear transitions)
- Dark mode with next-themes
- React Hook Form + Zod contact form
- Framer Motion page transitions
- Lottie animations via lottie-web

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-26 18:19:56 +08:00

69 lines
2.8 KiB
TypeScript

import Image from "next/image"
import Link from "next/link"
import type { BlogPost } from "@/lib/blog-data"
interface BlogCardProps {
post: BlogPost
variant?: "featured" | "grid"
}
export default function BlogCard({ post, variant = "grid" }: BlogCardProps) {
const isFeatured = variant === "featured"
return (
<div role="listitem" className={isFeatured ? "blog-featured-v1-wrapper w-dyn-item" : "blog-card-v3-wrapper w-dyn-item"}>
{isFeatured ? (
<div className="border-wrapper">
<CardInner post={post} variant={variant} />
</div>
) : (
<CardInner post={post} variant={variant} />
)}
{isFeatured && (
<div data-wf--corner-gradient-outline--variant="base" className="corner-gradient-wrapper">
<div className="corner-gradient-horizontal top-left" />
<div className="corner-gradient-horizontal bottom-left" />
<div className="corner-gradient-horizontal top-right" />
<div className="corner-gradient-horizontal bottom-right" />
</div>
)}
</div>
)
}
function CardInner({ post, variant }: { post: BlogPost; variant: "featured" | "grid" }) {
const isGrid = variant === "grid"
const cls = isGrid ? "blog-card-v1 w-variant-b9404c55-01d5-df76-2e4a-c99996f3231c w-inline-block" : "blog-card-v1 w-inline-block"
return (
<Link href={`/blog-posts/${post.slug}`} className={cls}>
<div className={`blog-v1-image-wrapper${isGrid ? " w-variant-b9404c55-01d5-df76-2e4a-c99996f3231c" : ""}`}>
<Image alt={post.imageAlt} src={post.image} className="image" fill style={{ objectFit: "cover" }} />
</div>
<div className={`blog-v1-content${isGrid ? " w-variant-b9404c55-01d5-df76-2e4a-c99996f3231c" : ""}`}>
<div className="inner-container _420px">
<h3 className={`display-6${isGrid ? " w-variant-b9404c55-01d5-df76-2e4a-c99996f3231c" : ""}`}>{post.title}</h3>
<div className="mg-top-4x-extra-small">
<p className="text-paragraph">{post.excerpt}</p>
</div>
<div className="mg-top-3x-extra-small">
<div className="blog-details-wrapper">
<div className="item-details">{post.date}</div>
<div className="item-details-divider">&middot;</div>
<div className="item-details">{post.category}</div>
</div>
</div>
</div>
<div className="bottom-right-button-wrapper">
<div className="icon-button">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 17 17" fill="none" className="squared-icon">
<path d="M6.25391 3.45312L10.7458 8.01563L6.25391 12.5781" stroke="currentColor" strokeWidth="1.5" strokeLinecap="square" />
</svg>
<div className="icon-button-bg" />
</div>
</div>
</div>
</Link>
)
}