# Blog Grid (Moonarc)

Shows blog posts as cards, with the first post featured across two columns. Cards reveal with a stagger and covers ease larger on hover. Each cover carries a transition name, so with Astro's router a click morphs it into the post's own cover. Give the post page the same name.

- Pro block. Install: `npx shadcn@latest add @moonarc-pro/blog-grid` (license key required)
- Tier B · category section · trigger scroll, hover, click
- Readout: `<BlogGrid posts={[…]} featured>`
- Browser support: newly (Chrome 111 · Firefox 144 · Safari 18); elsewhere: an instant swap into the post
- Measured cost: 0 B JS of its own · uses Reveal + runtime (with dependencies 3.0 kB raw; CSS 11.9 kB raw)
- Page: https://moonarc.dev/components/blog-grid/

## Props

| Prop | Type | Default | Description |
|---|---|---|---|
| `posts` | `{ href, title, excerpt?, date, cover?, tag? }[]` | none | Posts in order. |
| `featured` | `boolean` | `true` | Feature the first post across two columns. |
| `columns` | `2 | 3 | 4` | `3` | Columns on wide screens; the featured post spans two. |
| `tone` | `'surface' | 'muted' | 'ink' | 'brand'` | `unset (paints nothing)` | The ground: the page surface, a muted band, an always-dark ink panel, or a deep brand panel. Each paints --background, --ma-tone-muted (over --muted, with a --border hairline), --ma-tone-ink or --ma-tone-brand (over --primary) with the matching text. With theme.css, a painted tone also re-declares --card, --border, --input and --ring inside the section, so cards and fields follow the ground. Decoration is strongest on brand. |
| `density` | `'compact' | 'cozy' | 'roomy'` | `'cozy'` | Gaps ×0.8 / ×1 / ×1.25 through --ma-density. |

## Usage

```astro
---
import BlogGrid from '@/components/moonarc/pro/BlogGrid.astro';
---
<BlogGrid posts={posts.map((p) => ({ href: p.url, title: p.title, excerpt: p.excerpt, date: p.date, cover: { src: p.cover, alt: '' } }))} />

<!-- on the post page (import PageTransition from '@/components/moonarc/PageTransition.astro'), the same name morphs the cover: -->
<PageTransition name={`ma-cover-${url}`} preset="morph"><img src={cover} alt="" /></PageTransition>
```

## Reduced motion

Cards fade in without stagger; no cover scale; instant page swap.

## With ClientRouter

The cover morph is the router; everything else is CSS.

## Craft

- The transition name is derived from the post URL, so the grid and the post page agree without coordination.
- Covers scale to 1.03 on hover, on the preset curve. It is the only hover effect on the card.
- The whole card is the link (a pseudo-element on the title link), so the cover is clickable without a second anchor.

## Replaces

- Blog sections (Tailwind Plus)
- Blog (shadcnblocks)

## Source

Pro block. The source is served by the license-gated registry: `npx shadcn@latest add @moonarc-pro/blog-grid` with a key in components.json (https://moonarc.dev/account/). Everything it composes is free: reveal, page-transition.
