Skip to content

Listings

Listing Detail

A listing page: title, price and figures, a wide photo, then description, detail lists, gallery and video beside the agent, a tour form and nearby listings.

Layout and motion from the Findit template — see it in context

Installation

$ npx shadcn@latest add https://framebrick.co/r/blocks/listing-detail.json

Usage

import { ListingDetail } from "@/components/listing-detail";

<ListingDetail
  title="Palm Court Villa"
  type={{ label: "For rent", href: "/properties?type=rent" }}
  price="$7,900"
  priceSuffix="/month"
  image={{ src: "/listings/palm-court.jpg", alt: "…" }}
  video={{ url: "https://www.youtube.com/watch?v=…", poster: "/listings/palm-court-tour.jpg", title: "Palm Court Villa — video tour" }}
  onTourSubmit={async (data) => {
    await fetch("/api/tour", { method: "POST", body: data });
  }}
/>

Props

PropTypeDefaultDescription
titlestring—The page's h1.
type / category{ label, href? }—Chips above the title: filled, then muted.
price / priceSuffixstring—Beside the title from 768px; the suffix ("/month") is muted.
beds / baths / area / locationnumber | string—The figures and the area under the line.
image{ src, alt }—The wide photo (1140:646).
description / featuresstring[]—Paragraphs, and highlights with a check in two columns from 768px.
facts{ title, rows: { label, value }[] }[]Details, AmenitiesTitled lists of rows, two columns from 768px.
address / mapHrefstring—The location part; the map link opens in a new tab.
gallery{ src, alt }[]—The first photo across two columns, the rest two a row.
video{ url, poster, title }—A YouTube tour; with your own poster nothing is requested from YouTube before play.
agent{ name, image, detail?, href?, contacts }—Sidebar card: portrait, name, a muted line, contact rows and a profile button.
more{ title, href, address, price, image }[]—Nearby listings in the last sidebar card.
onTourSubmit(data: FormData) => Promise<void> | void—Sends the tour request (listing, name, email, phone, message); throw to show the error state. Without it the form pretends to send.
labelsobject—Every heading, label and button text; "{location}" in more is replaced.
classNamestring—Classes for the <section>.
  • Below 1024px the sidebar follows the content; from 1024px the sidebar is 375px wide beside it. Headings: the title is h1, every part and sidebar card an h2.
  • The tour form shows a spinner while sending, a thank-you and clears on success, an error on failure — announced to screen readers; typing again resets the button.
  • Buttons roll their label (flip-button); nearby listing photos grow to 105% on hover (zoom-card); the video loads YouTube only when played (lite-youtube).

AI prompt

Paste into v0, Lovable, Bolt or Claude to rebuild this block in your own project.

Create a React + Tailwind CSS block called ListingDetail (Next.js, client component) with shadcn Button, Input, Label and Textarea.
- <section className="pt-12 pb-(--section-y)">, container mx-auto max-w-(--container) px-(--gutter), column gap-12.
- Header: chips (type bg-primary, category bg-muted; links) over an h1 (font-heading text-h2 semibold); the price (same size) with a muted suffix
  beside it from 768px (items-end). A border-t row (pt-7.5): "Features" with Beds / Baths / Area and icons as a <dl>, and "Location" with a pin.
- A 1140:646 photo, rounded-xl.
- Then a column / from 1024px a row (gap-24): content (flex-1, parts gap-12, each an h2 text-h3 over its content): description paragraphs, highlights
  (check icons, 2 columns from 768px), detail lists (<dl> rows with border-b py-2.5, label muted left, value right; 2 columns from 768px), location
  with a map button, a gallery (first photo spanning 2 columns, 1140:646), a YouTube facade that loads the player on click with your own poster.
- Sidebar (lg: 375px): cards on bg-muted rounded-xl p-5: agent (72px round photo, name, muted line, contact rows, full-width profile button); a
  tour form (read-only property field, name*, email*, phone, message; submit with pending / success / error states and a role="status");
  nearby listings (photo 4:3 zooming to 1.05 on hover, title, address, price; 2 columns from 768px, 1 in the sidebar).
- Buttons roll their label on hover. Only shadcn variables and block tokens (secondary text on bg-muted is text-foreground/65: muted-foreground
  falls under 4.5:1 there); plain <img> with alt text.

Be the first to know

Get new templates and components first

One short email when we release a template or a free component. No spam — unsubscribe anytime.

We use your email only for Framebrick updates. Privacy policy