From the kitchen
A week at Ostria, plate by plate. Tap a photograph to see it larger and read where it came from.
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.
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.
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/hotel40?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
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.
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.
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:
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" }}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
eyebrow | string | – | Small uppercase line above the heading |
heading | string | – | Centered serif <h2>, revealed word by word through Text1 |
description | string | – | Paragraph under the heading |
photos | Dish[] | [] | Dishes in order; the grid shows the first six |
labels | Labels | {} | Accessible names for the open, close, previous and next controls |
className | string | – | Extra classes for the outer <section> |
type Dish = {
src: string;
alt: string;
title: string;
note: string;
};
type Labels = {
open?: string;
close?: string;
previous?: string;
next?: string;
};01 to 06 in their captions.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.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.photos array, so dishes past the sixth appear there but not in the grid.