Components / Blocks

BlogGrid

A blog index with a featured post, category filter, post cards, pagination and an in-place reader.

Install

npx shadcn@latest add https://irisui.dev/r/blog-grid.json
import { BlogGrid } from "@/components/iris/blocks/blog-grid/blog-grid";
Registry item blog-gridBrings in foundationRegistry JSON

Preview

BlogGrid

A blog index with a featured post, a category filter, a grid of post cards, pagination and an in-place reader that opens a post without leaving the page.

When to use

  • The index page of a blog, journal, changelog essays or customer stories.
  • When posts have a cover image, a category, an author and a reading time.
  • Not for release notes with versions and dates per change: use ChangelogFeed.
  • Not for a short "latest posts" strip in a footer or sidebar; render a simple list instead.

Usage

import { BlogGrid } from "@/components/iris/blocks/blog-grid/blog-grid";

h(BlogGrid, {
  title: "The notdocs blog",
  description: "Release notes, design decisions and engineering write-ups.",
  categories: ["Product", "Design", "Engineering", "Company"],
  posts: [
    {
      id: "files-in-your-repo",
      featured: true,
      category: "Product",
      date: "2026-10-06",
      readTime: 7,
      author: { name: "Katerina Vlachou", role: "Product lead", avatar: "/people/katerina.jpg" },
      title: "Your workspace is a folder in your repo",
      excerpt: "Pages, tasks and decisions are markdown files, and nothing syncs.",
      image: { src: "/covers/files-in-your-repo.jpg", alt: "A document tree beside its markdown file" },
      body: ["First paragraph.", "Second paragraph."],
    },
  ],
  pageSize: 6,
  getHref: undefined, // pass (post) => `/blog/${post.id}` to link out instead of the reader
});

Props

Prop Type Default Description
title / description string "Blog", sample line Heading and supporting text.
posts BlogPost[] 13 sample notdocs posts { id, title, excerpt, category, date (ISO), readTime (minutes), author: { name, avatar?, role? }, image?: { src, alt }, body?: string[], featured? }.
categories string[] Product, Design, Engineering, Company Filter labels in order; "All" is added in front.
category / defaultCategory / onCategoryChange string "All" Active category (controlled / uncontrolled).
page / defaultPage / onPageChange number 1 One-based page (controlled / uncontrolled).
pageSize number 6 Cards per page below the featured post.
showFeatured boolean true Shows the newest post of the current filter as a large card on page one.
getHref (post) => string none When set, cards are links and the in-place reader is off.
onPostOpen (post) => void none Called when a post opens, from a link or the reader.
className string none Extra class on the section.

Notes

  • The default posts are a sample notdocs blog with one flat inline SVG cover and no portraits; pass your own posts.
  • An author without avatar shows a plain placeholder circle (no initials).
  • The reader morphs the card image into the article header (shared layout); reduced motion replaces the morph with a fade.
  • Dates are formatted from the ISO string; posts are sorted newest first.