Kitchen Gallery with Story Lightbox

From the kitchen

Whatendsuponthetable.

A week at Ostria, plate by plate. Tap a photograph to see it larger and read where it came from.

01Breakfast under the vine
04Olives from the grove
02Bream, straight off the boat
05Blue hour at the bar
03Tomatoes at their best
06The long table
About this block

Kitchen Gallery with Story LightboxPRO

A six-photo food and dining gallery in three staggered columns of portrait and square frames with numbered serif titles; any photo opens a soft paper lightbox that shows the picture beside its title, a short note and a counter, with arrow buttons and arrow keys to move through the dishes.

Hotel40: Kitchen Gallery with Story Lightbox

Six food and dining photographs fall into three staggered columns of portrait and square frames with numbered serif titles, and any of them opens a soft paper lightbox that sets the picture beside its title, a short note and a counter, with arrow buttons and arrow keys to move through the dishes.

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/hotel40?email=YOUR_EMAIL&license_key=YOUR_KEY"

Base UI flavor

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

This installs the block to components/beste/block/hotel40.tsx plus the text1 word stagger used for the heading.

Quick start

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

tsx
import { Hotel40, hotel40Demo } from "@/components/beste/block/hotel40";

export default function Page() {
  return <Hotel40 {...hotel40Demo} />;
}

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

tsx
import { Hotel40 } from "@/components/beste/block/hotel40";

export default function Page() {
  return (
    <Hotel40
      eyebrow="From the kitchen"
      heading="What ends up on the table."
      description="A week at Ostria on Paros, plate by plate."
      photos={[
        {
          src: "https://oud.pics/b/hotel/ostria-breakfast-spread.webp",
          alt: "A breakfast table of yogurt, figs, bread and coffee under a vine",
          title: "Breakfast under the vine",
          note: "Sheep's yogurt, figs from the garden and bread baked at six.",
        },
        {
          src: "https://oud.pics/b/hotel/ostria-grilled-fish.webp",
          alt: "A whole grilled sea bream with charred lemon",
          title: "Bream, straight off the boat",
          note: "Grilled whole over vine cuttings and finished with our own oil.",
        },
        {
          src: "https://oud.pics/b/hotel/ostria-dining-terrace.webp",
          alt: "A long candlelit table under a vine pergola at dusk",
          title: "The long table",
          note: "Dinner for whoever is staying, plus a few friends from the village.",
        },
      ]}
      labels={{ open: "Open photo", close: "Close", previous: "Previous dish", next: "Next dish" }}
    />
  );
}

Props

PropTypeDefaultDescription
eyebrowstring–Small uppercase line above the heading
headingstring–Centered serif <h2>, revealed word by word through Text1
descriptionstring–Paragraph under the heading
photosDish[][]Dishes in order; the grid shows the first six
labelsLabels{}Accessible names for the open, close, previous and next controls
classNamestring–Extra classes for the outer <section>
ts
type Dish = {
  src: string;
  alt: string;
  title: string;
  note: string;
};

type Labels = {
  open?: string;
  close?: string;
  previous?: string;
  next?: string;
};

Behavior notes

  • Photos are dealt into three columns by index (1, 4 in the first; 2, 5 in the second; 3, 6 in the third), and frames alternate 4:5 portrait and square by position, numbered 01 to 06 in their captions.
  • From lg the middle column drops 6rem and the third 2rem for a staggered line. On sm the grid is two columns and the third column spans both, laying its two photos side by side; on a phone everything stacks.
  • Each column rises in once with a 0.1 second stagger by column, photos stay blurred until loaded, and hover zooms a photo to 105%.
  • Clicking a photo opens a role="dialog" lightbox on a translucent, blurred bg-background and locks the page scroll. The picture takes seven of twelve columns from md, beside a 01 / 06 counter, the title and the note.
  • Esc closes the lightbox, the left and right arrow keys and the round buttons step through the dishes, and stepping wraps at both ends. There is no swipe.
  • The lightbox steps through the whole photos array, so dishes past the sixth appear there but not in the grid.
  • With reduced motion the entrances and load blur are skipped and lightbox photos only crossfade instead of sliding 60px.

More Hotel blocks

View all Hotel
PRO

hotel39

Rooms Gallery with Filmstrip Lightbox

PRO

hotel41

Outdoors Gallery with Morph Lightbox

PRO

hotel7

Restaurant Terrace Story

Get Pro