blog/src/components/PostList.astro

93 lines
2.5 KiB
Text

---
import type { CollectionEntry } from 'astro:content'
import PinIcon from '@/assets/icons/pin-icon.svg'
import PostDate from '@/components/PostDate.astro'
import { defaultLocale } from '@/config'
import { generateDescription } from '@/utils/description'
import { isHomePage } from '@/utils/page'
type Post = CollectionEntry<'posts'> & {
remarkPluginFrontmatter: {
minutes: number
}
}
const { posts, lang, pinned = false } = Astro.props
const isHome = isHomePage(Astro.url.pathname)
export interface Props {
posts: Post[]
lang?: string
pinned?: boolean
}
function getPostPath(post: Post) {
// Prioritize abbrlink over slug
const postPath = post.data.abbrlink || post.id
// Add language prefix to URL if current page is in a language subdirectory and not the default language
return lang && lang !== defaultLocale ? `/${lang}/posts/${postPath}/` : `/posts/${postPath}/`
}
---
<ul>
{posts.map(post => (
<li
class="mb-5.5"
lg={isHome ? 'mb-10' : ''}
>
{/* post title */}
<h3 class="inline transition-colors hover:c-primary">
<a
class="cjk:tracking-0.02em"
lg={isHome ? 'font-medium text-4.5' : ''}
href={getPostPath(post)}
transition:name={`post-${post.data.abbrlink || post.id}-${lang}`}
data-disable-theme-transition
>
{post.data.title}
</a>
{/* pinned icon */}
{pinned && (
<PinIcon
aria-hidden="true"
class="ml-0.25em inline-block aspect-square w-0.98em translate-y--0.1em lg:(w-1.05em translate-y--0.15em)"
fill="currentColor"
/>
)}
</h3>
{/* mobile post time */}
<div
class="py-0.8 text-3.5 font-time lg:hidden"
transition:name={`time-${post.data.abbrlink || post.id}-${lang}`}
data-disable-theme-transition
>
<PostDate
date={post.data.published}
minutes={post.remarkPluginFrontmatter.minutes}
/>
</div>
{/* desktop post time */}
<div class="hidden text-3.65 font-time lg:(ml-2.5 inline)">
<PostDate
date={post.data.published}
minutes={post.remarkPluginFrontmatter.minutes}
/>
</div>
{/* desktop post description */}
{isHome && (
<div
class="heti hidden"
lg="mt-2.25 block"
>
<p>{generateDescription(post, 'list')}</p>
</div>
)}
</li>
))}
</ul>