Where it is
Drag the map to look around. The pin is the courtyard gate; the dots are the places the sales team mentions most, all inside a 12 minute walk.
Esri, Maxar, OpenStreetMap
The sales suite is in the warehouse lobby, open Tuesday to Saturday from 10 to 6. Laura Marling and the team will walk you round.
+44 20 7946 0000A location section for a development on a real map drawn without a map library: street and satellite tiles with a pill switch, dragging, double-click and keyboard zoom that glides between levels, a labelled pin for the development and small labelled dots for nearby places that centre the map when clicked, and a dark contact card over the corner with the sales suite hours, a large phone number and a directions button.
A location section for a development on a real map drawn without a map library: an eyebrow, heading and intro in the header grid, then street and satellite tiles with a pill switch, dragging, double-click and keyboard zoom that glides between levels, a labelled pin for the development and small labelled dots for nearby places that centre the map when clicked, and a dark contact card over the corner with the sales suite hours, a large phone number and a directions button.
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/realestate28?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://beste.dev/r-base/realestate28?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/realestate28.tsx plus the badge24 rule eyebrow, the button25 quiet pill used for the directions button, and the shadcn/ui button primitive behind it; the map, its tiles and controls are all inside the one file.
The installed file exports realestate28Demo alongside the block: the exact props behind the preview above. Spread it to get a working section in one line.
import { Realestate28, realestate28Demo } from "@/components/beste/block/realestate28";
export default function Page() {
return <Realestate28 {...realestate28Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { Realestate28 } from "@/components/beste/block/realestate28";
export default function Page() {
return (
<Realestate28
eyebrow="Where it is"
heading="On the river, six minutes from Mill Lane station"
description="Drag the map to look around. The pin is the courtyard gate."
home={{ title: "Alder Row", lat: 51.50642, lng: -0.09903 }}
center={{ lat: 51.50585, lng: -0.09635, zoom: 15 }}
places={[
{ title: "Mill Lane station", lat: 51.50426, lng: -0.09275 },
{ title: "Riverside Market", lat: 51.50565, lng: -0.09061 },
{ title: "Granary Square park", lat: 51.50829, lng: -0.10433 },
]}
styles={[
{
label: "Map",
url: "https://server.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer/tile/{z}/{y}/{x}",
maxZoom: 16,
invertInDark: true,
},
{
label: "Satellite",
url: "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
maxZoom: 18,
},
]}
attribution="Esri, Maxar, OpenStreetMap"
card={{
title: "See it in person",
description: "The sales suite is open Tuesday to Saturday from 10 to 6.",
phone: { label: "+44 20 7946 0000", href: "tel:+442079460000" },
button: { label: "Get directions", href: "https://www.google.com/maps/dir/?api=1&destination=51.50642,-0.09903" },
}}
labels={{ zoomIn: "Zoom in", zoomOut: "Zoom out", reset: "Back to Alder Row", map: "Map of Riverside around Alder Row", styles: "Map style" }}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
eyebrow | string | – | Short line above the heading, rendered through badge24. |
heading | string | – | Section heading. |
description | string | – | Intro paragraph beside the heading. |
home | Home | – | The development pin, with its name in a dark pill above the point. |
center | Center | – | Starting view; falls back to home at zoom 15. |
places | Place[] | [] | Labelled dots for nearby places; clicking one centres the map on it. |
styles | MapStyle[] | [] | Tile sources; a pill switch appears when there are two or more. |
attribution | string | – | Tile credit in the bottom right corner. |
card | ContactCard | – | Dark contact card over the bottom left of the map. |
labels | Labels | {} | Accessible names for the map, the style switch and the three controls. |
className | string | – | Extra classes merged onto the section. |
type Home = {
title: string;
lat: number;
lng: number;
};
type Center = {
lat: number;
lng: number;
zoom: number;
};
type Place = {
title: string;
lat: number;
lng: number;
};
type MapStyle = {
label: string;
url: string; // with {z}, {x} and {y} placeholders
maxZoom: number;
invertInDark?: boolean;
};
type ContactCard = {
title: string;
description: string;
phone: { label: string; href: string };
button?: { label: string; href: string };
};
type Labels = {
zoomIn?: string;
zoomOut?: string;
reset?: string;
map?: string;
styles?: string;
};maxZoom) so tiles stay sharp on dense screens, and each tile fades in once loaded. Zoom is clamped between 12 and 17.+, = or - zoom. The side buttons zoom in, zoom out and return to the starting view.prefers-reduced-motion the glides become instant jumps.invertInDark is inverted and hue-rotated in dark mode, which turns the light gray street map dark; satellite imagery is left as is. The style switch is a pair of segmented pills with aria-pressed.