summaryrefslogtreecommitdiff
path: root/src/components/blog/SinglePost.astro
diff options
context:
space:
mode:
authorDawid Rycerz <dawid@rycerz.xyz>2025-07-21 21:56:55 +0300
committerDawid Rycerz <dawid@rycerz.xyz>2025-07-21 21:56:55 +0300
commitc735556726e75428550a3d28a2cf58e2c8490b7d (patch)
treefd0ae29d1636b825abeedff6b99d3376bb383135 /src/components/blog/SinglePost.astro
Initial template
Diffstat (limited to 'src/components/blog/SinglePost.astro')
-rw-r--r--src/components/blog/SinglePost.astro103
1 files changed, 103 insertions, 0 deletions
diff --git a/src/components/blog/SinglePost.astro b/src/components/blog/SinglePost.astro
new file mode 100644
index 0000000..297cca9
--- /dev/null
+++ b/src/components/blog/SinglePost.astro
@@ -0,0 +1,103 @@
+---
+import { Icon } from 'astro-icon/components';
+
+import Image from '~/components/common/Image.astro';
+import PostTags from '~/components/blog/Tags.astro';
+import SocialShare from '~/components/common/SocialShare.astro';
+
+import { getPermalink } from '~/utils/permalinks';
+import { getFormattedDate } from '~/utils/utils';
+
+import type { Post } from '~/types';
+
+export interface Props {
+ post: Post;
+ url: string | URL;
+}
+
+const { post, url } = Astro.props;
+---
+
+<section class="py-8 sm:py-16 lg:py-20 mx-auto">
+ <article>
+ <header
+ class={post.image
+ ? 'intersect-once intersect-quarter motion-safe:md:opacity-0 motion-safe:md:intersect:animate-fade'
+ : 'intersect-once intersect-quarter motion-safe:md:opacity-0 motion-safe:md:intersect:animate-fade'}
+ >
+ <div class="flex justify-between flex-col sm:flex-row max-w-3xl mx-auto mt-0 mb-2 px-4 sm:px-6 sm:items-center">
+ <p>
+ <Icon name="tabler:clock" class="w-4 h-4 inline-block -mt-0.5 dark:text-gray-400" />
+ <time datetime={String(post.publishDate)} class="inline-block">{getFormattedDate(post.publishDate)}</time>
+ {
+ post.author && (
+ <>
+ {' '}
+ · <Icon name="tabler:user" class="w-4 h-4 inline-block -mt-0.5 dark:text-gray-400" />
+ <span class="inline-block">{post.author}</span>
+ </>
+ )
+ }
+ {
+ post.category && (
+ <>
+ {' '}
+ ·{' '}
+ <a class="hover:underline inline-block" href={getPermalink(post.category.slug, 'category')}>
+ {post.category.title}
+ </a>
+ </>
+ )
+ }
+ {
+ post.readingTime && (
+ <>
+ &nbsp;· <span>{post.readingTime}</span> min read
+ </>
+ )
+ }
+ </p>
+ </div>
+
+ <h1
+ class="px-4 sm:px-6 max-w-3xl mx-auto text-4xl md:text-5xl font-bold leading-tighter tracking-tighter font-heading"
+ >
+ {post.title}
+ </h1>
+ <p
+ class="max-w-3xl mx-auto mt-4 mb-8 px-4 sm:px-6 text-xl md:text-2xl text-muted dark:text-slate-400 text-justify"
+ >
+ {post.excerpt}
+ </p>
+
+ {
+ post.image ? (
+ <Image
+ src={post.image}
+ class="max-w-full lg:max-w-[900px] mx-auto mb-6 sm:rounded-md bg-gray-400 dark:bg-slate-700"
+ widths={[400, 900]}
+ sizes="(max-width: 900px) 400px, 900px"
+ alt={post?.excerpt || ''}
+ width={900}
+ height={506}
+ loading="eager"
+ decoding="async"
+ />
+ ) : (
+ <div class="max-w-3xl mx-auto px-4 sm:px-6">
+ <div class="border-t dark:border-slate-700" />
+ </div>
+ )
+ }
+ </header>
+ <div
+ class="mx-auto px-6 sm:px-6 max-w-3xl prose prose-md lg:prose-xl dark:prose-invert dark:prose-headings:text-slate-300 prose-headings:font-heading prose-headings:leading-tighter prose-headings:tracking-tighter prose-headings:font-bold prose-a:text-primary dark:prose-a:text-blue-400 prose-img:rounded-md prose-img:shadow-lg mt-8 prose-headings:scroll-mt-[80px] prose-li:my-0"
+ >
+ <slot />
+ </div>
+ <div class="mx-auto px-6 sm:px-6 max-w-3xl mt-8 flex justify-between flex-col sm:flex-row">
+ <PostTags tags={post.tags} class="mr-5 rtl:mr-0 rtl:ml-5" />
+ <SocialShare url={url} text={post.title} class="mt-5 sm:mt-1 align-middle text-gray-500 dark:text-slate-600" />
+ </div>
+ </article>
+</section>