fuwari/src/components/PostCard.astro
Katsuyuki Karasawa b016bd096c
fix: biome linter error (#369)
* fix(remark-excerpt): change loop variable to const for better readability

* fix(rehype-component-github-card): correct string quotes for consistency in title element

* fix(remark-directive-rehype): update biome-ignore comment for clarity on linting rule

* fix(rehype-component-admonition): use optional chaining for properties check and improve formatting

* fix(Pagination): improve equality checks and enhance code readability

* fix(TOC): correct equality check for consistency in removeTailingHash function

* fix(ImageWrapper): update import path to use 'node:path' for consistency

* fix(PostCard): update import path to use 'node:path' for consistency
2025-04-01 20:29:38 +09:00

106 lines
4.5 KiB
Text

---
import path from 'node:path'
import { Icon } from 'astro-icon/components'
import I18nKey from '../i18n/i18nKey'
import { i18n } from '../i18n/translation'
import { getDir } from '../utils/url-utils'
import PostMetadata from './PostMeta.astro'
import ImageWrapper from './misc/ImageWrapper.astro'
interface Props {
class?: string
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
entry: any
title: string
url: string
published: Date
updated?: Date
tags: string[]
category: string
image: string
description: string
draft: boolean
style: string
}
const {
entry,
title,
url,
published,
updated,
tags,
category,
image,
description,
style,
} = Astro.props
const className = Astro.props.class
const hasCover = image !== undefined && image !== null && image !== ''
const coverWidth = '28%'
const { remarkPluginFrontmatter } = await entry.render()
---
<div class:list={["card-base flex flex-col-reverse md:flex-col w-full rounded-[var(--radius-large)] overflow-hidden relative", className]} style={style}>
<div class:list={["pl-6 md:pl-9 pr-6 md:pr-2 pt-6 md:pt-7 pb-6 relative", {"w-full md:w-[calc(100%_-_52px_-_12px)]": !hasCover, "w-full md:w-[calc(100%_-_var(--coverWidth)_-_12px)]": hasCover}]}>
<a href={url}
class="transition group w-full block font-bold mb-3 text-3xl text-90
hover:text-[var(--primary)] dark:hover:text-[var(--primary)]
active:text-[var(--title-active)] dark:active:text-[var(--title-active)]
before:w-1 before:h-5 before:rounded-md before:bg-[var(--primary)]
before:absolute before:top-[35px] before:left-[18px] before:hidden md:before:block
">
{title}
<Icon class="inline text-[2rem] text-[var(--primary)] md:hidden translate-y-0.5 absolute" name="material-symbols:chevron-right-rounded" ></Icon>
<Icon class="text-[var(--primary)] text-[2rem] transition hidden md:inline absolute translate-y-0.5 opacity-0 group-hover:opacity-100 -translate-x-1 group-hover:translate-x-0" name="material-symbols:chevron-right-rounded"></Icon>
</a>
<!-- metadata -->
<PostMetadata published={published} updated={updated} tags={tags} category={category} hideTagsForMobile={true} hideUpdateDate={true} class="mb-4"></PostMetadata>
<!-- description -->
<div class:list={["transition text-75 mb-3.5 pr-4", {"line-clamp-2 md:line-clamp-1": !description}]}>
{ description || remarkPluginFrontmatter.excerpt }
</div>
<!-- word count and read time -->
<div class="text-sm text-black/30 dark:text-white/30 flex gap-4 transition">
<div>{remarkPluginFrontmatter.words} {" " + i18n(I18nKey.wordsCount)}</div>
<div>|</div>
<div>{remarkPluginFrontmatter.minutes} {" " + i18n(I18nKey.minutesCount)}</div>
</div>
</div>
{hasCover && <a href={url} aria-label={title}
class:list={["group",
"max-h-[20vh] md:max-h-none mx-4 mt-4 -mb-2 md:mb-0 md:mx-0 md:mt-0",
"md:w-[var(--coverWidth)] relative md:absolute md:top-3 md:bottom-3 md:right-3 rounded-xl overflow-hidden active:scale-95"
]} >
<div class="absolute pointer-events-none z-10 w-full h-full group-hover:bg-black/30 group-active:bg-black/50 transition"></div>
<div class="absolute pointer-events-none z-20 w-full h-full flex items-center justify-center ">
<Icon name="material-symbols:chevron-right-rounded"
class="transition opacity-0 group-hover:opacity-100 scale-50 group-hover:scale-100 text-white text-5xl">
</Icon>
</div>
<ImageWrapper src={image} basePath={path.join("content/posts/", getDir(entry.id))} alt="Cover Image of the Post"
class="w-full h-full">
</ImageWrapper>
</a>}
{!hasCover &&
<a href={url} aria-label={title} class="!hidden md:!flex btn-regular w-[3.25rem]
absolute right-3 top-3 bottom-3 rounded-xl bg-[var(--enter-btn-bg)]
hover:bg-[var(--enter-btn-bg-hover)] active:bg-[var(--enter-btn-bg-active)] active:scale-95
">
<Icon name="material-symbols:chevron-right-rounded"
class="transition text-[var(--primary)] text-4xl mx-auto">
</Icon>
</a>
}
</div>
<div class="transition border-t-[1px] border-dashed mx-6 border-black/10 dark:border-white/[0.15] last:border-t-0 md:hidden"></div>
<style define:vars={{coverWidth}}>
</style>