99 lines
4.3 KiB
Plaintext
99 lines
4.3 KiB
Plaintext
<!-- ---
|
|
import "../../styles/global.css"
|
|
import Layout from "../../layouts/Layout.astro"
|
|
import { getCollection } from 'astro:content';
|
|
import { Image } from 'astro:assets';
|
|
|
|
const posts = (await getCollection('workshop'))
|
|
.filter(post => !post.data.private)
|
|
.sort(
|
|
(a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf(),
|
|
);
|
|
---
|
|
|
|
<Layout>
|
|
<section class="max-w-7xl mb-10 sm:mb-14">
|
|
<h1 class="text-4xl sm:text-5xl font-bold mb-6 text-neutral-900 dark:text-neutral-100">Workshop</h1>
|
|
<p class="text-lg text-neutral-600 dark:text-neutral-400 leading-relaxed text-justify max-w-3xl">
|
|
I like to experiment, investigate and make mistakes. Here I archive my projects, ideas and failures.
|
|
</p>
|
|
</section>
|
|
|
|
{/* Grid layout for posts */}
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 sm:gap-6">
|
|
{posts.map((post) => (
|
|
<article class="group rounded-xl border border-neutral-200 dark:border-neutral-700 bg-white dark:bg-neutral-800 hover:shadow-lg transition-all duration-300 overflow-hidden flex flex-col">
|
|
<a href={`/workshop/${post.id}/`} class="block flex flex-col h-full">
|
|
{/* Hero Image */}
|
|
{post.data.heroImage && (
|
|
<div class="aspect-video overflow-hidden">
|
|
<Image
|
|
src={post.data.heroImage}
|
|
alt={post.data.title}
|
|
width={800}
|
|
height={450}
|
|
class="w-full h-full object-cover grayscale group-hover:grayscale-0 group-hover:scale-105 transition-all duration-300"
|
|
loading="lazy"
|
|
/>
|
|
</div>
|
|
)}
|
|
<div class="p-4 sm:p-6 flex flex-col flex-grow">
|
|
{/* Title */}
|
|
<h2 class="text-lg sm:text-xl font-semibold text-neutral-900 dark:text-neutral-100 group-hover:text-neutral-700 dark:group-hover:text-neutral-300 transition-colors mb-2 line-clamp-2">
|
|
{post.data.title}
|
|
</h2>
|
|
{post.data.description && (
|
|
<p class="text-sm sm:text-base text-neutral-600 dark:text-neutral-400 mb-4 line-clamp-3 leading-relaxed flex-grow">
|
|
{post.data.description}
|
|
</p>
|
|
)}
|
|
{post.data.tags && post.data.tags.length > 0 && (
|
|
<div class="flex flex-wrap gap-1.5 mb-4">
|
|
{post.data.tags.slice(0, 3).map((tag) => (
|
|
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-neutral-100 dark:bg-neutral-700 text-neutral-700 dark:text-neutral-300 hover:bg-neutral-200 dark:hover:bg-neutral-600 transition-colors">
|
|
#{tag}
|
|
</span>
|
|
))}
|
|
{post.data.tags.length > 3 && (
|
|
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-neutral-100 dark:bg-neutral-700 text-neutral-500 dark:text-neutral-400">
|
|
+{post.data.tags.length - 3}
|
|
</span>
|
|
)}
|
|
</div>
|
|
)}
|
|
{post.data.pubDate && (
|
|
<div class="flex items-center text-xs sm:text-sm text-neutral-500 dark:text-neutral-400 mt-auto">
|
|
<svg class="w-3 h-3 sm:w-4 sm:h-4 mr-1.5 sm:mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
|
|
</svg>
|
|
<time datetime={post.data.pubDate.toISOString()}>
|
|
{new Date(post.data.pubDate).toLocaleDateString('en-US', {
|
|
year: 'numeric',
|
|
month: 'short',
|
|
day: 'numeric'
|
|
})}
|
|
</time>
|
|
{post.data.updatedDate && (
|
|
<span class="ml-1 sm:ml-2 text-xs hidden sm:inline">
|
|
(Updated {new Date(post.data.updatedDate).toLocaleDateString('en-US', {
|
|
year: 'numeric',
|
|
month: 'short',
|
|
day: 'numeric'
|
|
})})
|
|
</span>
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</a>
|
|
</article>
|
|
))}
|
|
</div>
|
|
</Layout> -->
|
|
|
|
---
|
|
import WorkInProgress from "../../components/WorkInProgress.astro"
|
|
---
|
|
|
|
<WorkInProgress />
|