Skip to content
All Taste components

Blog

Blog — featured post with list

One large featured article on the left and a list of recent posts with small thumbnails on the right.

featured post · side list with thumbnails · reading time · stacks on mobile

import { ArrowRight } from "lucide-react";

type Post = { title: string; excerpt?: string; tag: string; href: string; cover: string; date: string; dateTime: string; minutes: number; author?: string };

const featured: Post = {
  title: "How to write payment terms clients actually read", excerpt: "Five lines that cut late payments without sounding strict, with examples you can copy.",
  tag: "Guides", href: "/blog/payment-terms", cover: "/blog/payment-terms.jpg", date: "Oct 8, 2026", dateTime: "2026-10-08", minutes: 6, author: "Ingrid Solberg",
};

const recent: Post[] = [
  { title: "Late fees: when to charge them and how much", tag: "Getting paid", href: "/blog/late-fees", cover: "/blog/late-fees.jpg", date: "Sep 29, 2026", dateTime: "2026-09-29", minutes: 8 },
  { title: "What’s new: recurring invoices for retainers", tag: "Product", href: "/blog/recurring-invoices", cover: "/blog/recurring.jpg", date: "Sep 17, 2026", dateTime: "2026-09-17", minutes: 3 },
  { title: "The month-end checklist for a one-person business", tag: "Guides", href: "/blog/month-end", cover: "/blog/month-end.jpg", date: "Sep 4, 2026", dateTime: "2026-09-04", minutes: 5 },
  { title: "Quotes vs estimates vs invoices, explained", tag: "Guides", href: "/blog/quotes-estimates", cover: "/blog/quotes.jpg", date: "Aug 21, 2026", dateTime: "2026-08-21", minutes: 4 },
];

export function BlogFeaturedList() {
  return (
    <section aria-labelledby="journal-title" className="bg-bg px-5 py-16 font-sans sm:px-10 sm:py-20">
      <div className="mx-auto max-w-6xl">
        <h2 id="journal-title" className="text-3xl font-semibold tracking-tight text-fg sm:text-4xl">The Tallybook journal</h2>

        <div className="mt-10 grid gap-9 lg:grid-cols-[1.25fr_1fr] lg:gap-12">
          <a href={featured.href} className="group grid content-start gap-3.5">
            <img src={featured.cover} alt="" className="mb-2 aspect-[16/10] w-full rounded-xl bg-primary-soft object-cover" />
            <div className="flex flex-wrap items-center gap-2.5 text-[13px] text-fg-subtle">
              <span className="rounded-full bg-primary-soft px-2 py-0.5 text-xs font-medium text-primary-soft-fg">Featured</span>
              <span>{featured.tag}</span><span aria-hidden>·</span><span>{featured.minutes} min read</span>
            </div>
            <h3 className="text-balance text-2xl font-semibold leading-tight tracking-tight text-fg group-hover:underline group-hover:underline-offset-4 sm:text-[28px]">{featured.title}</h3>
            <p className="text-[15px] leading-relaxed text-fg-muted">{featured.excerpt}</p>
            <p className="text-[13px] text-fg-subtle">{featured.author} · <time dateTime={featured.dateTime}>{featured.date}</time></p>
          </a>

          <div>
            <div className="mb-[18px] flex items-center justify-between">
              <h3 className="text-[13px] font-semibold uppercase tracking-wider text-fg-subtle">Recent</h3>
              <a href="/blog" className="inline-flex items-center gap-1 text-[13px] font-medium text-primary hover:underline">All posts <ArrowRight className="size-3.5" aria-hidden /></a>
            </div>
            <ul className="divide-y divide-border">
              {recent.map((p) => (
                <li key={p.href}>
                  <a href={p.href} className="group grid grid-cols-[88px_1fr] items-center gap-4 py-[18px] first:pt-0">
                    <img src={p.cover} alt="" className="aspect-square w-full rounded-lg bg-surface-2 object-cover" />
                    <div className="grid gap-1.5">
                      <p className="text-[15px] font-semibold leading-snug text-fg group-hover:underline group-hover:underline-offset-4">{p.title}</p>
                      <p className="flex flex-wrap gap-2 text-[13px] text-fg-subtle"><span>{p.tag}</span><span aria-hidden>·</span><time dateTime={p.dateTime}>{p.date}</time></p>
                    </div>
                  </a>
                </li>
              ))}
            </ul>
          </div>
        </div>
      </div>
    </section>
  );
}

The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.