




A mood section for a hotel: a light, centered line that turns into an italic serif second half, above a row of five photographs of different heights set in a gentle wave, rising in from the middle outwards over a muted band that grows up behind them, with the whole row drifting slightly as the page scrolls.
A centered light headline whose second half fades in as italic serif, above a row of five photographs cut to different heights so the row reads as a wave, rising from the middle outward over a muted band that grows up behind them while the whole row drifts sideways with the scroll.
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/hotel31?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://beste.dev/r-base/hotel31?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/hotel31.tsx. It has no other registry components or shadcn/ui primitives; motion comes from framer-motion.
The installed file exports hotel31Demo alongside the block: the exact props behind the preview above. Spread it to get a working section in one line.
import { Hotel31, hotel31Demo } from "@/components/beste/block/hotel31";
export default function Page() {
return <Hotel31 {...hotel31Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { Hotel31 } from "@/components/beste/block/hotel31";
export default function Page() {
return (
<Hotel31
heading={{
plain: "A week of salt, slow light and long lunches,",
accent: "and a few evenings on Paros you will keep talking about.",
}}
images={[
{ src: "https://oud.pics/b/hotel/ostria-terrace-chairs.webp", alt: "Two woven armchairs on a terrace facing the sea" },
{ src: "https://oud.pics/b/hotel/ostria-garden-room.webp", alt: "A bedroom opening onto a garden terrace" },
{ src: "https://oud.pics/b/hotel/ostria-grilled-fish.webp", alt: "A whole grilled sea bream with charred lemon" },
{ src: "https://oud.pics/b/hotel/ostria-rooftop-suite.webp", alt: "A rooftop plunge pool facing the sunset" },
{ src: "https://oud.pics/b/hotel/ostria-stone-room.webp", alt: "A plaster bed under a whitewashed stone vault" },
]}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
heading | Heading | – | Centered headline: a plain lead followed by an italic serif accent |
images | Image[] | [] | Photographs for the wave row; only the first five are used |
className | string | – | Extra classes for the outer <section> |
type Heading = {
plain: string;
accent: string;
};
type Image = {
src: string;
alt: string;
};images decides which photo gets which height.sm breakpoint the first and fifth frames are hidden, leaving three photos on a phone.heading the headline is not rendered, and with an empty images array the whole photo row and band are left out.