Room Detail Hotspots

Inside the Sea Suite

Nothingintheroomistherebyaccident.

Most of what you touch was made on the island or within a day's sail of it. Tap a point to read where it came from.

A linen bed facing a tall arched window that opens onto the sea, with an olive tree in a clay pot and a ceramic jug on a stool
  1. Heavy linen woven in Crete, dried on the roof so it smells faintly of salt and thyme.

    Woven in Crete

Linen, washed in sea air

About this block

Room Detail HotspotsPRO

A room story told through its objects: numbered points sit on the photograph where each detail is, and choosing a point or a row in the numbered list beside it lights both up and opens a short note on where the piece came from, with list rules drawing in as the section arrives.

Hotel24: Room Detail Hotspots

Numbered points pop onto a room photograph where each object sits, and hovering or clicking a point or its row in the numbered list beside it highlights both and expands a short note on where that piece came from.

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.

Upgrade Now

Installation

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

bash
npx shadcn add "https://beste.dev/r/hotel24?email=YOUR_EMAIL&license_key=YOUR_KEY"

Base UI flavor

bash
npx shadcn add "https://beste.dev/r-base/hotel24?email=YOUR_EMAIL&license_key=YOUR_KEY"

This installs the block to components/beste/block/hotel24.tsx plus the text1 word stagger it uses for the heading.

Quick start

The installed file exports hotel24Demo alongside the block: the exact props behind the preview above. Spread it to get a working section in one line.

tsx
import { Hotel24, hotel24Demo } from "@/components/beste/block/hotel24";

export default function Page() {
  return <Hotel24 {...hotel24Demo} />;
}

Then replace the demo with your own props. Written out, a trimmed setup looks like this:

tsx
import { Hotel24 } from "@/components/beste/block/hotel24";

export default function Page() {
  return (
    <Hotel24
      eyebrow="Inside the Sea Suite"
      heading="Nothing in the room is there by accident."
      description="Most of what you touch was made on the island. Tap a point to read where it came from."
      image={{
        src: "https://oud.pics/b/hotel/ostria-sea-suite.webp",
        alt: "A linen bed facing a tall arched window that opens onto the sea",
      }}
      details={[
        { title: "Linen, washed in sea air", description: "Heavy linen woven in Crete, dried on the roof.", maker: "Woven in Crete", x: 26, y: 70 },
        { title: "The arched door", description: "Cut into a wall seventy centimeters thick.", maker: "Built in 1962", x: 72, y: 40 },
        { title: "A water jug from Sifnos", description: "Refilled with cold water every afternoon.", x: 93, y: 58 },
      ]}
      labels={{ show: "Show detail" }}
    />
  );
}

Props

PropTypeDefaultDescription
eyebrowstring–Small uppercase line above the heading
headingstring–Serif <h2>, staggered word by word through Text1
descriptionstring–Paragraph at the right of the header
imageImage–The room photograph the points sit on
detailsDetail[][]One point and one list row per object
labelsLabels{}Prefix for each point's accessible label
classNamestring–Extra classes for the outer <section>
ts
type Image = {
  src: string;
  alt: string;
};

type Detail = {
  title: string;
  description: string;
  maker?: string;
  x: number; // percent from the left of the photo
  y: number; // percent from the top of the photo
};

type Labels = {
  show?: string;
};

Behavior notes

  • Each point is placed with left: x% and top: y% and centered on that spot, so coordinates are percentages of the 4:3 photo frame, not pixels.
  • Points and list rows share one active index: hovering or clicking either one sets it. The active point turns solid with a pinging ring, and the matching row brightens and expands its description and optional maker line with a height animation.
  • The first detail is active on load, and one row is always open.
  • Points scale in one after another (0.15s apart) once the section is in view, the list rows fade up and their top rules draw in from the left; all of these run once.
  • Each point has an accessible label of labels.show, its number and title, with aria-pressed on the active one; rows use aria-expanded, and a polite live region announces the active title.
  • The photo takes eight of twelve columns beside the list from the large breakpoint and stacks above it below that. With reduced motion the ping ring and entrance animations are skipped.

More Hotel blocks

View all Hotel
PRO

hotel3

Room Collection List

PRO

hotel39

Rooms Gallery with Filmstrip Lightbox

PRO

hotel41

Outdoors Gallery with Morph Lightbox

Get Pro