166 lines
4.5 KiB
Plaintext
166 lines
4.5 KiB
Plaintext
---
|
|
import Layout from './Layout.astro';
|
|
import FormattedDate from '../components/FormattedDate.astro';
|
|
import ShareButtons from '../components/ShareButtons.astro';
|
|
import TagList from '../components/TagList.astro';
|
|
import './styles/markdown.css';
|
|
|
|
import directus from '../../lib/directus';
|
|
import { readItems } from '@directus/sdk';
|
|
|
|
export async function getStaticPaths() {
|
|
const posts = await directus.request(
|
|
readItems('posts', {
|
|
fields: ['*'],
|
|
})
|
|
);
|
|
return posts.map((post) => ({ params: { slug: post.slug }, props: post }));
|
|
}
|
|
|
|
const post = Astro.props;
|
|
|
|
let canonicalURL;
|
|
try {
|
|
canonicalURL = new URL(Astro.url.pathname, Astro.site || process.env.SITE_URL);
|
|
} catch (error) {
|
|
console.error('Error creating canonical URL:', error);
|
|
canonicalURL = new URL('https://www.example.com');
|
|
}
|
|
---
|
|
|
|
<Layout title={post.title} description={post.description}>
|
|
<article class="prose prose-zinc dark:prose-invert lg:prose-lg mx-auto max-w-4xl">
|
|
<div class="hero-text mb-12">
|
|
<h1
|
|
class="mb-4 text-4xl font-bold tracking-tight text-zinc-900 sm:text-5xl dark:text-zinc-100"
|
|
>
|
|
{post.title}
|
|
</h1>
|
|
|
|
<p
|
|
class="mb-2 line-clamp-2 text-center text-sm text-zinc-600 sm:mb-3 sm:line-clamp-3 sm:text-left sm:text-base dark:text-zinc-400"
|
|
>
|
|
{post.description}
|
|
</p>
|
|
|
|
<div
|
|
class="hero-text mb-2 flex flex-wrap items-center justify-center gap-3 text-xs text-zinc-500 sm:mb-3 sm:justify-start sm:gap-4 sm:text-sm dark:text-zinc-400"
|
|
>
|
|
<FormattedDate date={post.published_date} />
|
|
</div>
|
|
|
|
<div
|
|
class="hero-text mb-2 flex flex-wrap items-center justify-center gap-3 text-xs text-zinc-500 sm:mb-3 sm:justify-start sm:gap-4 sm:text-sm dark:text-zinc-400"
|
|
>
|
|
<TagList tags={post.tags} />
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Hero image -->
|
|
{
|
|
post.image && (
|
|
<div class="relative mb-8 overflow-hidden rounded-xl shadow-lg sm:mb-12">
|
|
<div class="aspect-[16/9] w-full">
|
|
<img
|
|
src={`${process.env.DIRECTUS_URL ?? 'https://directus.alexlebens.dev'}/assets/${post.image}?width=500`}
|
|
alt={post.image_alt}
|
|
class="h-full w-full object-cover"
|
|
loading="eager"
|
|
/>
|
|
</div>
|
|
<div class="absolute inset-0 bg-gradient-to-t from-black/30 to-transparent" />
|
|
</div>
|
|
)
|
|
}
|
|
|
|
<div class="markdown-content">
|
|
<slot />
|
|
</div>
|
|
|
|
<!-- Add the like button after the content -->
|
|
<div class="mt-12 border-t border-zinc-200 pt-8 dark:border-zinc-800">
|
|
<div class="flex flex-col items-center justify-between gap-6 sm:flex-row">
|
|
<ShareButtons url={canonicalURL.toString()} title={post.title} />
|
|
</div>
|
|
</div>
|
|
|
|
{
|
|
post.updated_date && (
|
|
<div class="mt-8 text-sm text-zinc-500 italic dark:text-zinc-400">
|
|
Last updated on <FormattedDate date={post.updated_date} />
|
|
</div>
|
|
)
|
|
}
|
|
</article>
|
|
|
|
<slot name="after-article" />
|
|
</Layout>
|
|
|
|
<script>
|
|
document.addEventListener('astro:page-load', () => {
|
|
// Add smooth reveal animations for content after loading
|
|
const animateContent = () => {
|
|
// Animate hero section
|
|
const heroElements = document.querySelectorAll(
|
|
'.hero-text div, .hero-text ~ div, .hero-text h1, .hero-text span, .hero-text p, .hero-text + a'
|
|
);
|
|
heroElements.forEach((el, index) => {
|
|
setTimeout(
|
|
() => {
|
|
el.classList.add('animate-reveal');
|
|
},
|
|
100 + index * 150
|
|
);
|
|
});
|
|
|
|
// Animate posts with staggered delay
|
|
const articles = document.querySelectorAll('article.group');
|
|
articles.forEach((article, index) => {
|
|
setTimeout(
|
|
() => {
|
|
article.classList.add('animate-reveal');
|
|
},
|
|
500 + index * 150
|
|
);
|
|
});
|
|
};
|
|
|
|
animateContent();
|
|
});
|
|
</script>
|
|
|
|
<style>
|
|
/* Content reveal animations */
|
|
.hero-text h1,
|
|
.hero-text div,
|
|
.hero-text ~ div,
|
|
.hero-text span,
|
|
.hero-text p,
|
|
.hero-text + a,
|
|
article.group {
|
|
opacity: 0;
|
|
transform: translateY(20px);
|
|
transition:
|
|
opacity 0.8s ease,
|
|
transform 0.8s ease;
|
|
}
|
|
|
|
.animate-reveal {
|
|
opacity: 1 !important;
|
|
transform: translateY(0) !important;
|
|
}
|
|
|
|
/* Hero image styling */
|
|
article img:first-of-type {
|
|
border-radius: 1rem;
|
|
box-shadow:
|
|
0 10px 25px -5px rgba(0, 0, 0, 0.1),
|
|
0 8px 10px -6px rgba(0, 0, 0, 0.1);
|
|
transition: transform 0.3s ease;
|
|
}
|
|
|
|
article img:first-of-type:hover {
|
|
transform: scale(1.01);
|
|
}
|
|
</style>
|