radiatingstar/radiatingstar.com

View on GitHub
src/components/PostsList.astro

Summary

Maintainability
Test Coverage
---
import { CollectionEntry } from "astro:content";
import FormattedDate from "./FormattedDate.astro";
type Props = {
  posts: CollectionEntry<"blog">[];
  seeMoreUrl?: string;
};
const { posts, seeMoreUrl } = Astro.props;
function getRandomArbitrary(min, max) {
  return Math.random() * (max - min) + min;
}
const isFullyPacked = posts.length === 3;
---

<ul class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-2">
  {
    posts.map((post) => (
      <li class="rounded-2xl bg-slate-50 overflow-hidden group hover:bg-slate-100 transition-colors dark:bg-slate-800 dark:hover:bg-slate-700">
        <a href={`/blog/${post.slug}`} class="contents">
          <article class="flex flex-col h-full">
            <figure class="overflow-hidden rounded-2xl">
              <img
                alt=""
                width="350"
                height="170"
                class="rounded-2xl group-hover:scale-105 transition-all"
                src={`https://generative-placeholders.glitch.me/image?width=350&height=170&style=triangles&gap=100&img=${getRandomArbitrary(
                  0,
                  1000
                )}`}
              />
            </figure>
            <div class="p-4 flex flex-col gap-2 flex-1">
              <h3 class="text-lg text-foreground">{post.data.title}</h3>
              <p class="text-slate-500 dark:text-slate-400 text-sm">
                {post.data.description}
              </p>
              <footer class="text-sm -order-1 flex justify-between">
                <span class="text-slate-500 dark:text-slate-400">
                  <FormattedDate date={post.data.date} />
                </span>
                <span class="text-primary-red">
                  {post.data.tags.map(({ id }) => `#${id}`).join(" ")}
                </span>
              </footer>
            </div>
          </article>
        </a>
      </li>
    ))
  }
  {
    seeMoreUrl && (
      <li
        class:list={[
          "rounded-2xl bg-slate-50 dark:bg-slate-800 dark:hover:bg-slate-900 overflow-hidden hover:bg-slate-100 transition-colors text-slate-500 dark:text-slate-400 p-4",
          isFullyPacked && "md:max-lg:col-span-full",
        ]}
      >
        <a
          href={seeMoreUrl}
          class:list={[
            "items-center justify-center w-full h-full flex flex-col gap-2",
            isFullyPacked && "md:max-lg:flex-row-reverse",
          ]}
        >
          <svg
            xmlns="http://www.w3.org/2000/svg"
            width="24"
            height="24"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="1"
            stroke-linecap="round"
            stroke-linejoin="round"
            class:list={[
              "lucide lucide-chevron-right-circle w-12 h-12",
              isFullyPacked && "md:max-lg:w-6 md:max-lg:h-6",
            ]}
          >
            <circle cx="12" cy="12" r="10" />
            <path d="m10 8 4 4-4 4" />
          </svg>
          <span>See more</span>
        </a>
      </li>
    )
  }
</ul>