Rooms and suites
Every room is different because the house was never planned. Each one has thick walls, linen, a bath in stone and a window that frames something worth looking at.
Compare all twelve rooms

An arched door opens straight onto the terrace and the cove below.

Glass doors to a walled garden and an olive tree older than the house.

The oldest room, cool in August, under a whitewashed barrel vault.

A plunge pool and a shaded daybed on the highest terrace in the house.
A rooms overview for a small hotel: a pinned photograph that crossfades to whichever room is hovered or focused, with a nightly rate pill on the frame, beside a ruled list of serif room names, one-line descriptions and dotted facts like size, view and guests. Phones get each photo inline.
A two-column rooms overview: a sticky photograph on the left crossfades to whichever room is hovered or focused in the ruled list on the right, where each row holds a serif room name, a one-line summary and dotted facts.
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/hotel3?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://beste.dev/r-base/hotel3?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/hotel3.tsx plus the text1 word stagger behind the heading.
The installed file exports hotel3Demo alongside the block: the exact props behind the preview above. Spread it to get a working section in one line.
import { Hotel3, hotel3Demo } from "@/components/beste/block/hotel3";
export default function Page() {
return <Hotel3 {...hotel3Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { Hotel3 } from "@/components/beste/block/hotel3";
export default function Page() {
return (
<Hotel3
eyebrow="Rooms and suites"
heading="Four ways to wake up by the sea."
description="Every room is different because the house was never planned."
link={{ label: "Compare all twelve rooms", href: "/rooms" }}
rooms={[
{
name: "Sea Suite",
summary: "An arched door opens straight onto the terrace and the cove below.",
facts: ["42 m²", "Sea view", "2 guests"],
price: "€480",
priceUnit: "a night",
href: "/rooms/sea-suite",
image: { src: "https://oud.pics/b/hotel/ostria-sea-suite.webp", alt: "A linen bed facing a tall arched window onto the sea" },
},
{
name: "Garden Room",
summary: "Glass doors to a walled garden and an old olive tree.",
facts: ["34 m²", "Private garden", "2 guests"],
price: "€360",
priceUnit: "a night",
href: "/rooms/garden-room",
image: { src: "https://oud.pics/b/hotel/ostria-garden-room.webp", alt: "A bedroom with glass doors open onto a garden terrace" },
},
]}
labels={{ from: "From" }}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
eyebrow | string | – | Uppercase line above the heading |
heading | string | – | Serif <h2>, staggered word by word through Text1 |
description | string | – | Paragraph to the right of the heading |
link | TextLink | – | Text link with an arrow under the description |
rooms | Room[] | [] | The rooms in the list, each with its own photograph |
labels | Labels | {} | Word placed before every price |
className | string | – | Extra classes for the outer <section> |
type TextLink = {
label: string;
href: string;
};
type Room = {
name: string;
summary: string;
facts: string[];
price: string;
priceUnit: string;
href: string;
image: { src: string; alt: string };
};
type Labels = {
from?: string;
};labels.from, the price and the unit.scaleX as they enter the viewport (once), and rows fade up with a 0.1 second stagger.href.