Tessel Peak, guided expeditions since 1998
A pinned scroll hero for an expedition company. A giant heavy word is cut out of the page surface as a window onto a full-bleed mountain photo, with a quiet eyebrow above it. As the visitor scrolls, the camera flies into the first letter on an exponential zoom, the photo drifting closer more slowly for depth, until the landscape fills the frame; then the heading, intro, an Arrow Pill and an underline link settle in over a soft scrim at the lower left. Built on the type-window component; reduced motion shows the open photo with the copy.
A pinned hero where a giant word is cut out of the page surface by the type-window component as a window onto a full-bleed photo, and scrolling flies the camera into one letter on an exponential zoom until the landscape fills the frame; then a headline, an intro, an Arrow Pill and an underline link settle in over a scrim at the lower left.
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/hero247?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/hero247?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/hero247.tsx plus the type-window component and the button23 and button2 buttons it uses.
The installed file exports hero247Demo alongside the block: the exact props behind the preview above. Spread it to get a working hero in one line.
import { Hero247, hero247Demo } from "@/components/beste/block/hero247";
export default function Page() {
return <Hero247 {...hero247Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { Hero247 } from "@/components/beste/block/hero247";
export default function Page() {
return (
<Hero247
eyebrow="Tessel Peak, guided expeditions since 1998"
heading="Go past the edge of the map."
description="Small-group treks through the Dolomites, Patagonia and the Lofoten coast."
buttons={[
{ label: "Plan an expedition", href: "/plan" },
{ label: "See the routes", href: "/routes" },
]}
typeWindow={{
word: "Horizon",
imageSrc: "https://images.unsplash.com/photo-1506744038136-46273834b3fb?auto=format&fit=crop&w=2400&q=80",
imageAlt: "A mountain valley and lake at first light",
surface: "background",
fontWeight: 800,
fit: 0.9,
depth: 0.5,
}}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
eyebrow | string | – | Quiet line above the word, shown only before the flight starts |
heading | string | – | Headline revealed once the photo fills the frame, rendered as the page h1 |
description | string | – | Intro under the headline |
buttons | ActionButton[] | [] | The first renders as a light Arrow Pill (Button23), the rest as light underline links (Button2) |
typeWindow | Omit<TypeWindowProps, "progress" | "autoplay" | "paused" | "className" | "children"> | – | Forwards the TypeWindow props from the type-window component, including the required imageSrc plus the word, alt text, target letter, speed, surface, font weight, tracking, fit, depth and interactive |
className | string | – | Extra classes for the outer <section> |
type ActionButton = {
label: string;
href: string;
};260svh tall with a sticky stage; scroll progress from 0.04 to 0.7 drives the flight from 0 to 1 with autoplay forced off. The camera flies into the middle letter unless letter is set.0.1 and returns below 0.05; the scrim and copy appear above 0.72 and leave below 0.64. The gaps keep either state from flickering at its threshold.surface: "foreground" cuts the word from a dark surface and switches the eyebrow to text-background/70; the closing copy sits on the photo, so it stays white over a black scrim in every theme.typeWindow is set; with interactive on, the photo drifts gently with the pointer.