Split hero pairing a statement, paragraph and two pill CTAs with a pair of captioned portrait images, the second dropped by a stagger on desktop so the column reads as an editorial spread.
A two-column hero where the copy sits beside a pair of captioned portraits, the second dropped down the page so the pictures read as prints pinned at different heights rather than a tidy pair of cards.
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/hero150?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/hero150?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/hero150.tsx plus the badge7 eyebrow and button12 pill button it uses.
The installed file exports hero150Demo alongside the block: the exact props behind the preview above. Spread it to get a working hero in one line.
import { Hero150, hero150Demo } from "@/components/beste/block/hero150";
export default function Page() {
return <Hero150 {...hero150Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { Hero150 } from "@/components/beste/block/hero150";
export default function Page() {
return (
<Hero150
badge={{ label: "Studio, since 2014" }}
heading="Two pictures usually settle it faster than two decks."
description="We work in images from the first week: rough, printed, pinned to a wall."
buttons={[
{ label: "Look at the work", href: "/work", tone: "dark" },
{ label: "Book a studio visit", href: "/contact", tone: "outline" },
]}
images={[
{ src: "/studio/specimens.jpg", alt: "Specimen sheets on a table", caption: "Specimen table, week two" },
{ src: "/studio/wall.jpg", alt: "Reviewing prints on a wall", caption: "Wall review, week five" },
]}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
badge | { label: string } | – | Eyebrow label rendered as a Badge7 |
heading | string | – | Display statement, rendered as the page h1 |
description | string | – | Supporting paragraph under the statement |
buttons | ActionButton[] | [] | CTAs rendered as Button12, each with its own tone |
images | CaptionedImage[] | [] | Portraits in the right column, every second one offset |
className | string | – | Extra classes for the outer <section> |
type CaptionedImage = {
src: string;
alt: string;
caption: string;
};
type ActionButton = {
label: string;
href: string;
tone?: "dark" | "outline";
};md:mt-16 on every odd image, so it only appears from md up; on a phone the two portraits stay level and the column reads as a plain pair.tone defaults to "dark", so a button list with no tone set still renders a solid primary pill first.figure and figcaption elements, with the caption under the frame as plain muted text rather than on a scrim.aspect-[3/4] for every image, so a landscape source is cropped into the pair rather than breaking the offset rhythm.md:items-center, which keeps the copy optically level with a picture column that is taller on one side than the other.max-w-xl while the section runs to max-w-7xl, so the statement holds a readable measure instead of stretching across the column.flex-wrap gap-3, so a third CTA drops to a second line at its natural width rather than compressing the row.hero112
Two-column studio hero with a two-tone headline, dual CTAs, tall image and a client wordmark strip.
hero121
Split hero with a big headline and CTA on the left, a divided vertical stat rail on the right, and a full-width wide image strip below.
hero156
Edge-to-edge split hero: a dark half carries the statement, paragraph, outline pill CTA and a ruled detail row, while the other half is a full-height photograph with a pill caption in its corner.