Book a viewing
Viewings take about 45 minutes and start at the sales suite on Mill Lane. Pick a day and a time, leave your details, and Jon Hopkins will confirm by email within one working day.
A viewing request for a development's sales page: eyebrow, heading and lead across the top, then a two-column GET form with a pill-shaped date field that opens a shadcn calendar limited to future days, a row of time-slot pills writing to a hidden input, and name, email and phone fields beside them, closing on a hairline with the submit pill and a note.
A viewing request for a development's sales page: eyebrow, heading and lead across the top, then a two-column GET form. On the left a pill-shaped date field opens a shadcn calendar limited to future days and a row of time-slot pills writes the chosen time to a hidden input; on the right sit name, email and phone fields, closing on a hairline with the submit pill and a note about opening hours.
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/realestate43?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://beste.dev/r-base/realestate43?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/realestate43.tsx plus the badge24 rule eyebrow, the button25 quiet pill used for the submit button, and the shadcn/ui button, calendar, input and popover primitives behind them, the date picker and the three text fields.
The installed file exports realestate43Demo alongside the block: the exact props behind the preview above. Spread it to get a working section in one line.
import { Realestate43, realestate43Demo } from "@/components/beste/block/realestate43";
export default function Page() {
return <Realestate43 {...realestate43Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { Realestate43 } from "@/components/beste/block/realestate43";
export default function Page() {
return (
<Realestate43
eyebrow="Book a viewing"
heading="See the show apartment and walk the courtyard."
description="Viewings take about 45 minutes and start at the sales suite on Mill Lane."
form={{
action: "/viewings",
params: { date: "date", time: "time", name: "name", email: "email", phone: "phone" },
}}
slots={["10:00", "12:00", "15:00"]}
locale="en-US"
labels={{
date: "Day",
pick: "Choose a day",
time: "Time",
name: "Full name",
email: "Email",
phone: "Phone",
submit: "Request this viewing",
}}
note="The sales suite is open Monday to Saturday."
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
eyebrow | string | – | Short line above the heading, drawn with a rule in front of it. |
heading | string | – | Section heading. |
description | string | – | Lead paragraph, right-aligned to the heading on wide screens. |
form | ViewingForm | – | GET target and the query parameter names; without it no form renders. |
slots | string[] | [] | Time slots shown as pills, submitted verbatim. |
locale | string | – | Locale for the chosen day's label in the trigger, en-US when omitted. |
labels | Labels | {} | Captions for the date field, the slot row, the three text fields and the submit pill. |
note | string | – | Short line beside the submit button. |
className | string | – | Extra classes merged onto the section. |
type ViewingForm = {
action: string;
params?: { date?: string; time?: string; name?: string; email?: string; phone?: string };
};
type Labels = {
date?: string;
pick?: string;
time?: string;
name?: string;
email?: string;
phone?: string;
submit?: string;
};method="get" form posting to form.action; every parameter name comes from form.params and falls back to date, time, name, email and phone. The three text fields carry native required.Calendar inside a Popover, single-select, with every day before today disabled; today is read on the client after mount so server and client markup match. Picking a day closes the popover and writes the local YYYY-MM-DD value to a hidden input.aria-pressed pills; the chosen slot goes to a second hidden input. Submitting without a day opens the calendar instead; submitting without a time focuses the first slot pill.toLocaleDateString in the locale prop (weekday, month, day).prefers-reduced-motion nothing moves.Wiring the form up
This block ships the form markup only; state, validation, and submit are yours to add. Our guide wires the shadcn Field primitives to React Hook Form, TanStack Form, and Formisch on one field system.