
What living here is like
The bedroom faces the birches, so the light in the morning is green and moving. I have not set an alarm since we moved in.
One large buyer quote beside a 4:3 photograph that opens from the top once it has loaded and drifts gently against the scroll, with the buyer's name and the home they bought on a hairline row and a counter with previous and next buttons that cycle through the quotes with a cross-fade.
One large buyer quote beside a 4:3 photograph for a development's sales page. The photograph opens from the top once it has loaded and drifts gently against the scroll; the quote sits large on the right with the buyer's name and the home they bought on a hairline row beneath it, and a counter with previous and next buttons cycles through the quotes with a short cross-fade.
Upgrade to Pro
Pro blocks install through the shadcn CLI with your license key and ship their full source. Docs and live previews stay open to everyone, so you can read every block's details first.
Swap YOUR_EMAIL and YOUR_KEY for the email and license key on your account. Find your license key on your account page.
Radix flavor
npx shadcn add "https://beste.dev/r/realestate50?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://beste.dev/r-base/realestate50?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/realestate50.tsx plus the badge24 eyebrow above the quote; the previous and next controls are plain buttons, so no shadcn/ui primitives are needed.
The installed file exports realestate50Demo alongside the block: the exact props behind the preview above. Spread it to get a working section in one line.
import { Realestate50, realestate50Demo } from "@/components/beste/block/realestate50";
export default function Page() {
return <Realestate50 {...realestate50Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { Realestate50 } from "@/components/beste/block/realestate50";
export default function Page() {
return (
<Realestate50
eyebrow="What living here is like"
image={{
src: "https://oud.pics/b/realestate/alder-warehouse-bedroom.webp",
alt: "The main bedroom of a warehouse home, an oak bed against the brick wall",
}}
quotes={[
{
quote: "The bedroom faces the birches, so the light in the morning is green and moving.",
name: "Joni Mitchell",
detail: "Type B, two bedroom with study",
},
{
quote: "The children are at St Olave's in 8 minutes and I am at the station in 6.",
name: "Bill Evans",
detail: "Type D, four bedroom",
},
]}
labels={{ previous: "Previous quote", next: "Next quote", of: "of" }}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
eyebrow | string | – | Short line above the quote, drawn with a rule in front of it. |
image | { src: string; alt: string } | – | The 4:3 photograph beside the quote; without it the text spans eight columns. |
quotes | Quote[] | [] | The testimonials to cycle through; the first one shows on load. |
labels | Labels | {} | Accessible names for the two arrow buttons and the word between the counter's numbers. |
className | string | – | Extra classes merged onto the section. |
type Quote = {
quote: string;
name: string;
detail: string;
};
type Labels = {
previous?: string;
next?: string;
of?: string;
};load event and on entering the viewport: only then does the frame open from the top over 1.6 seconds while the image settles from a 1.18 to a 1.12 scale, and a scroll-linked transform moves it from -6% to 6% as the section passes.AnimatePresence in wait mode: the old text fades out in 0.2 seconds and the new one rises in over 0.6 seconds.1 of 3 using labels.of and is marked aria-live="polite", so screen readers hear the change; the controls only render when there is more than one quote.prefers-reduced-motion the frame and text render in place, the parallax is held at its start value and quote changes swap without an entrance.