ComponentsSite blocks

Blog list

Latest posts and category archives. It receives posts as data (PostSummary) — any CMS maps into that shape; in stored pages an f.query field is resolved by the app's resolvers.posts. Each post is an article with one link on its title that covers the whole item (::after), dates are time[datetime], pagination is plain URLs in a labelled nav.

blocks/site/blog-list.tsx, blocks/site/registry-2.ts, styles/blocks.csstheme · material · accent · density · font

From the journal

Installation

$ pnpm add @vamos-ui/react

The whole kit as one package — get updates by bumping the version. Add the styles to globals.css: @import "@vamos-ui/react/styles.css";

Usage

import { BlogList, BlogListSkeleton, type PostSummary } from "@vamos-ui/react/blocks";

const posts: PostSummary[] = await cms.posts({ limit: 6 }).then(toPostSummary);

<BlogList title="From the *journal*" posts={posts} allLink={{ href: "/journal", label: "All posts" }}
  pagination={{ page, total, hrefTemplate: "/journal?page={page}" }} />

// Streaming
<Suspense fallback={<BlogListSkeleton />}><LatestPosts /></Suspense>

Examples

List with categories and pagination

Date · title + excerpt · reading time rows. Categories are links with aria-current; page 1 drops ?page=1.

Journal

Notes from the kitchen

Grid (SaaS guides)

Three columns of 3:2 covers without card frames.

Guides

Run a calmer front desk

Empty state and skeleton

No posts: a message and an optional action (newsletter). BlogListSkeleton is the Suspense fallback.

Events

No events planned yet

Wine nights and fish suppers are announced here and by email, usually two weeks ahead.

API

BlogList

PropTypeDefault
variant
Layout.
"editorial" | "list" | "grid" | "compact""editorial"
posts
{ href, title, excerpt?, cover?, category?, publishedAt, readingMinutes?, author? }.
PostSummary[]—
categories
Category filter links.
{ label; href; active? }[]—
pagination
Prev / next links and “Page 2 of 5”. href() for code, hrefTemplate for JSON.
{ page; total; href?(p) ; hrefTemplate? }—
allLink
“All posts” beside the header.
{ href; label }—
showCovers
Covers in editorial and grid.
booleantrue
empty
Empty-state copy.
{ title?; text?; action? }—
postHeadingLevel
Default 3 under a title, else 2.
2 | 3 | 4—
eyebrow / title / lead
Section header.
ReactNode—
labels / locale
“{count} min read”, pagination strings; dates via Intl.
Partial<Site2Labels> / string—
theme / anchor / id / className / headingLevel / components / editMode
Shared block props.
BlockBaseProps—

BlogListSkeleton

PropTypeDefault
variant / count
aria-hidden placeholder shapes.
BlogListVariant / number"grid" / 3