Skip to content

Listings

Listings Filter

A page title, then a filter card that stays in view beside the listings from 1024px and folds away below; chips narrow the grid.

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

Installation

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

Usage

import { ListingsFilter } from "@/components/listings-filter";

<ListingsFilter
  title="Find a place that fits"
  listings={[
    {
      title: "White Pool House",
      href: "/properties/white-pool-house",
      image: { src: "/listings/pool-house.jpg", alt: "…" },
      type: "For sale",
      category: { label: "Villas", href: "/properties?category=villas" },
      location: "Coral Hills",
      beds: 5,
      baths: 4,
      area: "3,900 sqft",
      price: "$1,950,000",
    },
  ]}
/>

Props

PropTypeDefaultDescription
as"h1" | "h2""h1"Heading level — h1 when the block opens a listings page.
label / title / leadstring—Muted line, heading (text-h1) and the lead beside it from 768px.
filterTitle / filterTextstringExplore:The filter card's title — the current choices follow it — and its text.
groupLabels{ type, category, location }Type, Category, LocationGroup titles; each group lists the values found in the listings, after an "All" chip.
listingsFilterListing[]6 listings{ title, href, image, type, category: { label, href? }, location, beds, baths, area, agent?, price }.
emptyTextstring—Shown when no listing matches.
countText(count) => string"6 listings"Read out by screen readers when the list changes.
stickyTopnumber120Distance from the top of the window while the card is stuck — the height of your sticky header plus a gap.
classNamestring—Classes for the <section>.
  • From 1024px the 342px filter card sticks while the two-column list scrolls beside it; below 1024px it spans the width above the list and its filters fold away behind a round button (filter-panel: height spring bounce 0, 0.4s, then a fade).
  • One choice per group; "All" clears it. Findit makes every filter a page of its own — for that, render filter-panel with links (href and active) instead.
  • Hovering a card grows its photo to 105% (zoom-card).

AI prompt

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

Create a React + Tailwind CSS block called ListingsFilter (Next.js, client component).
- <section className="py-(--section-y)">, container mx-auto max-w-(--container) px-(--gutter), column gap-12.
- Split title: a small muted label and an h1 (font-heading text-h1 semibold); beside it from 768px (items-end) a muted lead up to 400px.
- Below, a column that becomes a row from 1024px (items-start, gap-12): a filter card (rounded-lg border bg-card p-5; lg: 342px wide, sticky 120px
  from the top) with a title "Explore: <choices>", a muted text and three chip groups (Type, Category, Location; an uppercase muted h3 each, then
  rounded-full chips, the chosen one bg-primary). Below 1024px the groups fold away behind a round primary button between two lines and open by
  height with a spring (bounce 0, 0.4s) and a fade.
- Choosing a chip filters the list in place (one choice per group; "All" clears it); a visually hidden role="status" says the count.
- The list: 1 / 2 (768px) columns of full listing cards (rounded-xl bg-muted; a 350px photo zooming to 1.05 on hover, category and type chips;
  location with a pin, h3 title, Beds / Baths / Area, a border-t row with the agent and the price). An empty message on bg-muted when none match.
- 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