diff options
| author | aman333nolawz <amananudhiu@gmail.com> | 2026-03-02 21:49:13 +0530 |
|---|---|---|
| committer | aman333nolawz <amananudhiu@gmail.com> | 2026-03-02 21:49:13 +0530 |
| commit | d41eff9eccf66644c4c60f53cb516bf079937a28 (patch) | |
| tree | 248a0863a3181369f943d678ec4273911d35efac /src/components/BlogCard.astro | |
Using astro-erudite for static site generation
Diffstat (limited to 'src/components/BlogCard.astro')
| -rw-r--r-- | src/components/BlogCard.astro | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/src/components/BlogCard.astro b/src/components/BlogCard.astro new file mode 100644 index 0000000..1a74025 --- /dev/null +++ b/src/components/BlogCard.astro @@ -0,0 +1,105 @@ +--- +import AvatarComponent from '@/components/ui/avatar' +import { Badge } from '@/components/ui/badge' +import { Separator } from '@/components/ui/separator' +import { + getCombinedReadingTime, + getSubpostCount, + isSubpost, + parseAuthors, +} from '@/lib/data-utils' +import { formatDate } from '@/lib/utils' +import { Icon } from 'astro-icon/components' +import { Image } from 'astro:assets' +import type { CollectionEntry } from 'astro:content' +import Link from './Link.astro' + +interface Props { + entry: CollectionEntry<'blog'> +} + +const { entry } = Astro.props +const formattedDate = formatDate(entry.data.date) +const readTime = await getCombinedReadingTime(entry.id) +const authors = await parseAuthors(entry.data.authors ?? []) +const subpostCount = !isSubpost(entry.id) ? await getSubpostCount(entry.id) : 0 +--- + +<div + class="hover:bg-muted/50 rounded-xl border p-4 transition-colors duration-300 ease-in-out" +> + <Link + href={`/${entry.collection}/${entry.id}`} + class="flex flex-col gap-4 sm:flex-row" + > + { + entry.data.image && ( + <div class="w-full sm:max-w-3xs sm:shrink-0"> + <Image + src={entry.data.image} + alt={entry.data.title} + width={1200} + height={630} + class="object-cover" + /> + </div> + ) + } + + <div class="grow"> + <h3 class="mb-1 text-lg font-medium">{entry.data.title}</h3> + <p class="text-muted-foreground mb-2 text-sm">{entry.data.description}</p> + + <div + class="text-muted-foreground mb-2 flex flex-wrap items-center gap-x-2 text-xs" + > + { + authors.length > 0 && ( + <> + {authors.map((author) => ( + <div class="flex items-center gap-x-1.5"> + <AvatarComponent + client:load + src={author.avatar} + alt={author.name} + fallback={author.name[0]} + className="size-5 rounded-full" + /> + <span>{author.name}</span> + </div> + ))} + <Separator orientation="vertical" className="h-4!" /> + </> + ) + } + <span>{formattedDate}</span> + <Separator orientation="vertical" className="h-4!" /> + <span>{readTime}</span> + { + subpostCount > 0 && ( + <> + <Separator orientation="vertical" className="h-4!" /> + <span class="flex items-center gap-1"> + <Icon name="lucide:file-text" class="size-3" /> + {subpostCount} subpost{subpostCount === 1 ? '' : 's'} + </span> + </> + ) + } + </div> + + { + entry.data.tags && ( + <div class="flex flex-wrap gap-2"> + {entry.data.tags.map((tag) => ( + <Badge variant="muted" className="flex items-center gap-x-1"> + <Icon name="lucide:hash" class="size-3" /> + {tag} + </Badge> + ))} + </div> + ) + } + </div> + </Link> +</div> |
