Silver Hour, a film photography studio in Lisbon
Tour, studio and portrait work on 35mm and medium format, developed by hand. Every roll keeps a little of the light that got in.
A dark film photography hero over the light-leak background component: warm blooms of light burn in from the edges of the frame, swell and fade under a film grain, and the nearest one leans toward the cursor. An oversized headline, an intro, a light Arrow Pill and an underline link sit at the top; a row of series links runs along the bottom, and hovering or focusing one fades its own light colors and edges into the frame. Every leak setting passes through the leak prop, and each series carries its own colors.
A dark hero over the light-leak component: warm film light leaks burn in from the edges of the frame under a grain. The headline, intro and buttons sit at the top, and a row of series links runs along the bottom; hovering or focusing a series fades its own light into the frame.
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://ui.beste.co/r/hero266?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/hero266?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/hero266.tsx plus the light-leak background and the button23 and button2 buttons it uses.
The installed file exports hero266Demo alongside the block: the exact props behind the preview above. Spread it to get a working hero in one line.
import { Hero266, hero266Demo } from "@/components/beste/block/hero266";
export default function Page() {
return <Hero266 {...hero266Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { Hero266 } from "@/components/beste/block/hero266";
export default function Page() {
return (
<Hero266
eyebrow="Silver Hour, a film photography studio in Lisbon"
heading="Shot on film, left in the light."
description="Tour, studio and portrait work on 35mm and medium format, developed by hand."
buttons={[
{ label: "Book a shoot", href: "/book" },
{ label: "See the archive", href: "/archive" },
]}
series={[
{ title: "On the road with Phoebe Bridgers", note: "Tour, 2025", href: "/tour", colors: ["#ff5a1f", "#ffb03a", "#ff2e63"], edges: "sides" },
{ title: "Night sessions at Harpa", note: "Studio, Reykjavik", href: "/harpa", colors: ["#e0287a", "#8a3ffc", "#ff9f43"], edges: "corners" },
]}
leak={{ baseColor: "#0c0908", burn: 0.55, grain: 0.2 }}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
eyebrow | string | – | Small line above the headline |
heading | string | – | Oversized headline, rendered as the page h1 |
description | string | – | Intro under the headline |
buttons | ActionButton[] | [] | The first renders as a light Arrow Pill, every later one as a Button2 underline link |
series | Series[] | [] | Links along the bottom; the first one's light shows on load |
seriesLabel | string | "Series" | Accessible name for the series nav |
leak | Omit<LightLeakProps, "className" | "children" | "colors"> | – | Forwarded to the LightLeak component: base color, leak count, edges, size, intensity, burn, fringe, flicker, speed, saturation, grain, transition, seed and interactive |
className | string | – | Extra classes for the outer <section> |
type ActionButton = {
label: string;
href: string;
};
type Series = {
title: string;
note?: string;
href: string;
colors: string[]; // 1 to 6 leak colors
edges?: "all" | "corners" | "top" | "bottom" | "sides"; // falls back to leak.edges
};colors and edges to LightLeak: the colors crossfade over leak.transition seconds and the leaks glide to their new edges. The last previewed series stays, so the light never snaps back when the pointer leaves.text-white with opacity steps) over a black/60 radial veil at the upper left, so the copy stays legible whatever the leaks do. The veil does not follow leak.baseColor; retune it for a light base.IntersectionObserver and on hidden tabs and respects prefers-reduced-motion: the copy then renders without its rise and palettes swap without fading.max(640px, 100svh - 78px), with the copy at the top and the series row anchored to the bottom.