A hotel hero built around a wide mixed-media carousel: silent films play through and photographs drift slowly for a set time before the next slide crossfades in, with a numbered caption that says whether it is a film or a photo, previous, pause and next controls, and a strip of thumbnails marked for films whose hairlines fill with each slide.
A serif headline and book pill sit above a wide carousel that mixes silent films, which play through to their end, with photographs that drift slowly for a set time, crossfading slide to slide under a numbered caption, previous, pause and next controls, and a thumbnail strip whose hairlines fill as each slide plays.
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/hotel38?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://beste.dev/r-base/hotel38?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/hotel38.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 hotel38Demo alongside the block: the exact props behind the preview above. Spread it to get a working section in one line.
import { Hotel38, hotel38Demo } from "@/components/beste/block/hotel38";
export default function Page() {
return <Hotel38 {...hotel38Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { Hotel38 } from "@/components/beste/block/hotel38";
export default function Page() {
return (
<Hotel38
eyebrow="Ostria in motion"
heading="Moments from an ordinary day on Paros."
description="Films and photographs from one week in June."
button={{ label: "Book a stay", href: "/book", tone: "dark" }}
slides={[
{
type: "video",
src: "https://oud.pics/b/hotel/ostria-video-exterior.mp4",
poster: "https://oud.pics/b/hotel/ostria-exterior-golden.webp",
alt: "The hotel on its hillside above the cove at golden hour",
caption: "The house as the sun drops",
},
{
type: "image",
src: "https://oud.pics/b/hotel/ostria-breakfast-spread.webp",
alt: "A breakfast table of yogurt, figs, bread and coffee",
caption: "Breakfast in the dappled shade",
},
{
type: "video",
src: "https://oud.pics/b/hotel/ostria-video-boat-cove.mp4",
poster: "https://oud.pics/b/hotel/ostria-boat-cove.webp",
alt: "A small wooden boat in a clear turquoise cove",
caption: "Anchored in the third cove",
},
]}
interval={6}
labels={{ film: "Film", photo: "Photo", previous: "Previous", next: "Next", play: "Play", pause: "Pause", show: "Show" }}
/>
);
}| 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 |
slides | Slide[] | [] | Films and photographs in carousel order |
interval | number | 6 | Seconds a photo stays on screen before advancing |
labels | Labels | {} | Caption words and accessible names for the controls and thumbnails |
className | string | – | Extra classes for the outer <section> |
type ActionButton = {
label: string;
href: string;
tone?: "primary" | "light" | "dark" | "outline";
};
type Slide = {
type: "video" | "image";
src: string;
poster?: string;
alt: string;
caption: string;
};
type Labels = {
film?: string;
photo?: string;
previous?: string;
next?: string;
play?: string;
pause?: string;
show?: string;
};requestAnimationFrame clock drives the strip: a photo counts its own elapsed time against interval, while a film reports currentTime / duration and advances on its ended event, so a film slide lasts exactly as long as the file.interval plus 1.2 seconds. The carousel wraps from the last slide back to the first.02 / 06, Photo, using labels.film or labels.photo by slide type, and swaps with a short slide up.poster or a photo's src and carry a small play badge for films. Below sm the thumbnail images and the previous button are hidden, leaving the hairlines as the progress strip.sm and 21:9 from lg.