Nicholai 058655f23d Add blog components and enhance blog functionality
- Introduced new BlogCard and BlogFilters components for improved blog post presentation and filtering capabilities.
- Updated content configuration to include fields for featured posts, categories, and tags.
- Enhanced the blog index page to display a featured post and editor's picks, along with a filterable grid for latest posts.
- Added a new blog entry on the G-Star Raw Olympics campaign with associated metadata for better categorization and tagging.
2025-12-08 03:58:22 -07:00

149 lines
4.4 KiB
Plaintext

---
import { Image } from 'astro:assets';
import type { ImageMetadata } from 'astro';
import FormattedDate from './FormattedDate.astro';
interface Props {
title: string;
description: string;
pubDate: Date;
heroImage?: ImageMetadata;
category?: string;
tags?: string[];
href: string;
variant?: 'default' | 'compact' | 'featured';
class?: string;
}
const {
title,
description,
pubDate,
heroImage,
category,
tags,
href,
variant = 'default',
class: className = '',
} = Astro.props;
// Compute estimated read time (rough estimate: 200 words per minute)
// For now, we'll show a placeholder since we don't have word count in frontmatter
const readTime = '5 min read';
const isCompact = variant === 'compact';
const isFeatured = variant === 'featured';
---
<article class:list={[
'group relative border border-white/10 bg-white/[0.02] hover:border-brand-accent/40 transition-all duration-500 overflow-hidden',
isFeatured ? 'lg:grid lg:grid-cols-2' : '',
className
]}>
<!-- Accent indicator strip -->
<div class="absolute top-0 left-0 w-1 h-full bg-slate-700 opacity-50 group-hover:bg-brand-accent group-hover:opacity-100 transition-all duration-500"></div>
<!-- Image section -->
<a href={href} class:list={[
'block relative overflow-hidden',
isFeatured ? 'aspect-[16/10] lg:aspect-auto lg:h-full' : isCompact ? 'aspect-[16/9]' : 'aspect-[16/9]'
]}>
{heroImage && (
<Image
src={heroImage}
alt=""
width={isFeatured ? 800 : 720}
height={isFeatured ? 500 : 360}
class="w-full h-full object-cover transition-transform duration-[1.2s] ease-out group-hover:scale-105"
/>
)}
<div class="absolute inset-0 bg-brand-dark/40 group-hover:bg-brand-dark/20 transition-colors duration-500"></div>
<div class="absolute inset-0 bg-gradient-to-t from-brand-dark/60 to-transparent"></div>
<!-- Category badge overlay -->
{category && (
<div class="absolute top-4 left-4">
<span class="px-3 py-1.5 text-[10px] font-mono font-bold uppercase tracking-widest bg-brand-dark/80 border border-white/20 text-white backdrop-blur-sm">
{category}
</span>
</div>
)}
</a>
<!-- Content section -->
<div class:list={[
'flex flex-col',
isFeatured ? 'p-8 lg:p-12 justify-center' : isCompact ? 'p-5' : 'p-6 lg:p-8'
]}>
<!-- Technical header with metadata -->
<div class="flex items-center gap-3 mb-4">
<span class="text-[10px] font-mono text-brand-accent uppercase tracking-widest">
<FormattedDate date={pubDate} />
</span>
<span class="h-px flex-grow max-w-8 bg-white/20"></span>
<span class="text-[10px] font-mono text-slate-500 uppercase tracking-widest">
{readTime}
</span>
</div>
<!-- Title -->
<a href={href}>
<h3 class:list={[
'font-bold text-white uppercase tracking-tight mb-3 group-hover:text-brand-accent transition-colors duration-300 leading-tight',
isFeatured ? 'text-3xl lg:text-4xl' : isCompact ? 'text-lg' : 'text-xl lg:text-2xl'
]}>
{title}
</h3>
</a>
<!-- Description -->
<p class:list={[
'text-slate-400 font-light leading-relaxed',
isFeatured ? 'text-base lg:text-lg line-clamp-3 mb-8' : isCompact ? 'text-sm line-clamp-2 mb-4' : 'text-sm line-clamp-2 mb-6'
]}>
{description}
</p>
<!-- Tags (only for featured and default variants) -->
{tags && tags.length > 0 && !isCompact && (
<div class="flex flex-wrap gap-2 mb-6">
{tags.slice(0, 4).map((tag) => (
<span class="px-2 py-1 text-[10px] font-mono uppercase border border-white/10 text-slate-500 group-hover:border-white/20 transition-colors">
{tag}
</span>
))}
</div>
)}
<!-- Read link -->
<div class:list={[
'flex items-center',
isFeatured ? 'mt-auto pt-6 border-t border-white/10' : 'mt-auto'
]}>
<a
href={href}
class="inline-flex items-center gap-3 text-xs font-bold uppercase tracking-widest text-slate-500 group-hover:text-white transition-all duration-300"
>
Read Article
<span class="block w-6 h-[1px] bg-slate-600 group-hover:bg-brand-accent group-hover:w-10 transition-all duration-300"></span>
<svg
xmlns="http://www.w3.org/2000/svg"
width="12"
height="12"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="opacity-0 -translate-x-2 group-hover:opacity-100 group-hover:translate-x-0 transition-all duration-300"
>
<path d="M5 12h14" />
<path d="m12 5 7 7-7 7" />
</svg>
</a>
</div>
</div>
</article>