An artistic hotel hero where the film is seen first through a small round window that opens on load, then widens with the scroll until the looping room film fills its whole frame while easing back from a slight zoom, beside a serif headline, a short line, a book pill and a play and pause control.
A serif headline sits beside a short line and a book pill, above a looping room film first seen through a small round window that opens on load and then widens with the scroll until the film fills its whole frame, easing back from a zoom as it goes.
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/hotel37?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://beste.dev/r-base/hotel37?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/hotel37.tsx plus the button22 sliding-marker pill used for the book action and the text1 word stagger used for the headline.
The installed file exports hotel37Demo alongside the block: the exact props behind the preview above. Spread it to get a working section in one line.
import { Hotel37, hotel37Demo } from "@/components/beste/block/hotel37";
export default function Page() {
return <Hotel37 {...hotel37Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { Hotel37 } from "@/components/beste/block/hotel37";
export default function Page() {
return (
<Hotel37
eyebrow="The Sea Suite"
heading="Wake up and let the curtains do the talking."
description="An arched door, salt air through the linen and the Paros cove waiting outside."
button={{ label: "Book the Sea Suite", href: "/rooms/sea-suite", tone: "dark" }}
video={{
src: "https://oud.pics/b/hotel/ostria-video-sea-suite.mp4",
poster: "https://oud.pics/b/hotel/ostria-sea-suite.webp",
label: "Linen curtains moving beside an arched door open onto the sea",
}}
labels={{ play: "Play", pause: "Pause" }}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
eyebrow | string | – | Small line above the headline |
heading | string | – | Serif <h1>, revealed word by word through Text1 |
description | string | – | Short paragraph in the right-hand column |
button | ActionButton | – | Pill action through Button22; tone defaults to dark |
video | Video | – | The film seen through the round window |
labels | Labels | {} | Accessible names for the play and pause button |
className | string | – | Extra classes for the outer <section> |
type ActionButton = {
label: string;
href: string;
tone?: "primary" | "light" | "dark" | "outline";
};
type Video = {
src: string;
poster: string;
label: string;
};
type Labels = {
play?: string;
pause?: string;
};circle() clip path. On load the circle animates from 0 to a 24% radius over 1.8 seconds after a 0.5 second delay.aria-label from the video's play and pause events; it sits outside the clip, so it stays visible while the window is small.sm; from lg the headline takes eight of twelve columns and the description column the other four.video the stage and its play button are not rendered.