Listing card

A Listing as a card, varying by kind.

A Listing rendered as a card, frameless: there is no box and no tinted band, so the card sits on the page. The photo leads, with the name and address under it as its caption, and a round Spring green arrow, the card's one Spring green shape: the print's sticker, small, on what the card does rather than on the price (a filled price reads as a sale). Then come the price in Black, the kind line, and the specs as one plain line (area · rooms · deposit) (ADR 0037). Availability sits on the kind line, separated and colour-coded by a single dot (one per state, ADR 0010) rather than carried in a chip of its own. The label is free copy, so a state word and a date read the same way (last card). Presentational: all strings are pre-localized by the caller.

Chips sit on the photo, in two independent corners:Open house top-left, and the New flag with the Availability state stacked under it top-right. Each carries its own solid fill, so text contrast is against the chip rather than whatever the photo happens to be (ADR 0007), and each corner is its own stack — an empty corner occupies nothing. Availability shows for every state except available: a chip on every card is noise, and the kind line still says the state in words. The midline holds the photo arrows; bottom-right is still reserved, not built, for an "AI enhanced" chip.

The photo strip (ADR 0030). The card takesimages, and the data decides — not kind: more than one photo adds prev/next arrows, a 3 / 12 counter bottom-left, swipe and mouse-drag; one photo is the plain still it always was. The second and fourth cards below have a single photo on purpose, so both shapes sit in one grid. Only slide one is in the markup — the rest ride in an inert <template> the browser never fetches, cloned in on first intent (hover or focus with a mouse, anIntersectionObserver on touch, which has no hover to wait for). Move a mouse over a card to see the arrows: they hide on(hover: hover) and (pointer: fine) and stay visible on anything else. The card is still one tab stop — tab to it and page the photos with ←/→. The strip loops, unlike the MediaCarousel and Gallery stages: an arrow that hid itself at the end would uncover the photo's own link right where the cursor was about to press, so the last photo opened the listing instead of wrapping.

Whole-card availability. Two of the four states change the card itself, in tones rather than in a contrasting block, fromdata-status on the root. Reserved gives the arrow the reserved status colours (held, not gone; nothing else changes). Let greys the arrow anddesaturates the photo, so the card retires. Available and Coming soon are deliberately untouched: available is the default, and dimming a coming-soon home would say the opposite of what it means.

The unit kind

Tone
  • 1 / 5
    Open house
    NewComing soon

    Strandgade 7, 1.5000 Odense C

    6.950 kr/md.LejlighedComing soon
    42 m²1 room1 month dep.
  • 1 / 2
    Let

    Bredgade 44, 3.5200 Odense V

    9.500 kr/md.LejlighedLet
    63 m²2 rooms2 months dep.
  • 1 / 1
    Coming soon

    Havnegade 21, 4.5000 Odense C

    7.800 kr/md.LejlighedAvailable from 1 Dec 2026
    51 m²2 rooms2 months dep.

The property kind

kind="property": a development or building shown with general info — area and rooms ranges and a read-more cue, no single price, type or deposit (GLOSSARY.md). Same component, varies by kind; we do not keep a separate PropertyCard. Passed a statusLabel it carries a filled status pill (ADR 0022) instead of the unit kind's inline dot. The third card is let, so the whole-card treatment shows on the property shape too.

Tone

Props

packages/primitives/src/ListingCard.astro
PropTypeRequired
kind

The Listing kind (GLOSSARY.md): a "unit" is a single home (price, type, deposit, status); a "property" is a development/building shown with general info (ranges, no single price), a read-more cue, and no status.

"unit" | "property"—
images

The home's photos, in order. One renders a plain still, exactly as this card always has; more than one makes the photo pageable (ADR 0030). The card does not decide this from `kind` — the data does, so a property with a photo set pages as readily as a unit.

CardPhoto[]yes
availability"available" | "reserved" | "let" | "coming-soon"—
statusLabel

What the card says about the state, in the kind line. Free copy: a coming-soon home may read "Available from 1 Dec 2026" rather than "Coming soon".

string—
availabilityLabel

The state's own name — always the plain word ("Coming soon"), never a date. The photo chip uses this: a corner chip is a glance, and a glance wants the state, not the detail. Falls back to statusLabel when not given.

string—
isNewboolean—
newLabelstring—
openHouse

An open-house event on this home. Its own flag, not an Availability state and not a kind of "new" — a Let home can still hold an open house, and a home can be New *and* holding one, in which case both badges show (ADR 0010 amendment).

boolean—
openHouseLabelstring—
priceLabelstring—
kindLabelstring—
addressstringyes
addressSecondarystring—
areaLabelstring—
roomsLabelstring—
depositLabelstring—
readMoreLabel

property kind: visible "read more" cue (the whole card is still the link).

string—
hrefstring—
headingLevel1 | 2 | 3 | 4 | 5 | 6—
eager

The card is in the first screen of a page (the top row of a grid): its lead photo loads at once instead of lazily. A lazy image in view waits for layout before it is even requested, and on the listings pages that photo is what the page is waiting on. Off by default, since most cards are below the fold.

boolean—
priority

The first card of a page: on a phone it is the only one in view, and its photo is the page's largest paint. Requested ahead of the other eager photos (fetchpriority="high"), which would otherwise share the bandwidth equally. One card per page at most.

boolean—
CardPhoto — referenced by a prop above
FieldTypeRequired
srcstringyes
srcset

The photo at several widths; the card says how wide it renders (PHOTO_SIZES below) and the browser picks. Without it the card loads `src`.

string—
altstring—