# Listing Grid (Moonarc)

Homes as cards (the building drawn by HomeArt, the price, the address, the beds, the baths and the area) with filters that work with no script: a group of radios for the kind of home and one for the least bedrooms, and :has() rules written for the list at build hide every card that does not match. The count over the cards and the note when nothing matches are worked out at build for every pair of choices, so they are words in the page, read out as they change. A card can carry a view-transition-name so it grows into its own page. Zero JavaScript.

- Pro block. Install: `npx shadcn@latest add @moonarc-pro/listing-grid` (license key required)
- Tier B · category section · trigger click, scroll
- Readout: `<ListingGrid listings={[{ href, title, price, kind, beds, art }]} kinds={…} beds={…} />`
- Browser support: newly (Chrome 105 · Firefox 121 · Safari 15.4); elsewhere: without :has() every card shows and the filters do nothing
- Measured cost: 0 B JS of its own · uses Reveal + runtime (with dependencies 3.0 kB raw; CSS 16.1 kB raw)
- Page: https://moonarc.dev/components/listing-grid/

## Props

| Prop | Type | Default | Description |
|---|---|---|---|
| `listings` | `{ href; title; address?; price; kind; beds; baths?; area?; badge?; art; transition? }[]` | none | The homes. kind is the value the kind filter matches; price and area are written as given; art is HomeArt's kind, seed, time and block. |
| `kinds` | `{ legend; all; options: { value; label }[] }` | none | The kind filter. Unset, none. |
| `beds` | `{ legend; any; options: number[] }` | none | The bedrooms filter: the least numbers offered. Unset, none. |
| `words` | `{ count?; one?; none?; bed?; beds?; bath?; baths? }` | `English` | The count ({n} is the number), its singular, the note when nothing matches and the units. |
| `columns` | `2 | 3 | 4` | `3` | Cards a row on a wide screen. |
| `headline` | `string` | none | The heading. Slot "headline" wins. |
| `eyebrow` | `string` | none | A short line above the heading. |
| `copy` | `string` | none | A line under the heading. |
| `level` | `1 | 2 | 3` | `2` | Heading level of the heading; each card's title is one below. 1 under a page's own heading with no heading of the grid's own: the titles are h2. |
| `tone` | `'surface' | 'muted' | 'ink' | 'brand'` | `unset (paints nothing)` | The section's ground. |
| `density` | `'compact' | 'cozy' | 'roomy'` | `'cozy'` | Block padding ×0.8 / ×1 / ×1.25 through --ma-density. |

## Usage

```astro
---
import ListingGrid from '@/components/moonarc/pro/ListingGrid.astro';
---
<ListingGrid
  headline="Homes for sale"
  kinds={{ legend: 'Kind', all: 'All', options: [{ value: 'house', label: 'Houses' }, { value: 'apartment', label: 'Flats' }] }}
  beds={{ legend: 'Bedrooms', any: 'Any', options: [1, 2, 3, 4] }}
  listings={[
    { href: '/homes/12-linden-row/', title: '12 Linden Row', address: 'Linden Hill', price: '$845,000', kind: 'house', beds: 4, baths: 2, area: '142 m²', art: { kind: 'house', seed: '12 Linden Row', block: 2 } },
    { href: '/homes/4-quay-street/', title: '4 Quay Street', address: 'Old Harbour', price: '$520,000', kind: 'apartment', beds: 2, baths: 1, area: '74 m²', badge: 'New', art: { kind: 'apartment', seed: '4 Quay Street', block: 3 } },
  ]}
/>
```

## Reduced motion

The cards arrive at once; a filter hides and shows them with no movement.

## With ClientRouter

CSS and Reveal; a filter picked is the page's own state and resets with the page.

## Craft

- The filters are radios in fieldsets, so the keyboard moves along them and a screen reader hears each group's legend. The rules that hide a card are written for this list at build (a card carries data-kind and the thresholds it is under in data-below), printed once beside it.
- The count over the cards is one sentence for each pair of choices, written at build, the matching one shown in a polite live region: it is a word in the page, where a CSS counter would be a picture of a number.
- The note when nothing matches is written only for the pairs that match nothing, so it never shows over a card.

## Replaces

- Listing grids filtered with a client-side script
- IDX listing widgets for simple sites

## Source

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