Bento Hero React component
A black and white bento of rounded tiles around a serif headline. Scroll and the centre photo grows to fill the hero while the other tiles slide away, revealing a heading, counting stats and a glass button.
About the Bento Hero component
Bento Hero opens as a quiet black and white grid: a serif headline on the centre photo, with rounded tiles of pictures, numbers and copy around it. Scrolling turns it into a film. The centre photo grows to fill the hero while the other tiles slide out through their own edges.
Once the picture has taken over, a heading, a thin divider, counting stats and a glass button fade in on top. Everything is tied to the scroll position, so it plays forwards and backwards with the visitor.
When to use it
Use it for brands with strong photography, like sport, fashion, film and editorial sites, where the first screen should feel composed rather than busy.
It needs a good central picture. If you have product screenshots rather than photos, a product-led hero will do more for you.
Installation
Add the Bento Hero component to your project with the shadcn CLI. It lands in components/bento-hero.tsx as plain React + Tailwind CSS source you own and can edit.
npx shadcn@latest add @reactframe/bento-heroOr copy the source by hand and install its dependencies:
npm install clsx tailwind-mergeProps
<BentoHero /> accepts 15 props, all optional. It also accepts the usual <section> attributes, like className, style, id and aria-*, and passes them to its root element.
| Prop | Type | Default |
|---|---|---|
| theme | "dark" | "light" | "dark" |
| title The serif headline on the centre tile. | string | "Keep Moving" |
| eyebrow | string | "Field notes, volume nine" |
| description | string | "Gear, routes and training plans from people who go out in every weather." |
| action | { label: string; href?: string; onClick?: () => void } | null | { label: "See the collection" } |
| image Photo in the centre tile, the one that grows to fill the hero. | string | "/demo/26.webp" |
| alt | string | "A rider and horse at full gallop, blurred with speed" |
| video Plays in the centre tile instead of the photo. | string | — |
| sideImages The two photo tiles at the sides. | [string, string] | ["/demo/23.webp", "/demo/34.webp"] |
| revealHeading Shown once the centre tile has filled the hero. | string | "Built for the long way round." |
| revealDescription | string | "Every route is walked, ridden and rewritten by the people who publish it." |
| stats The first two also get tiles of their own. | { value: number; suffix?: string; label: string }[] | DEFAULT_STATS |
- theme"dark" | "light"Default: "dark"
- title
The serif headline on the centre tile.
stringDefault: "Keep Moving" - eyebrowstringDefault: "Field notes, volume nine"
- descriptionstringDefault: "Gear, routes and training plans from people who go out in every weather."
- action{ label: string; href?: string; onClick?: () => void } | nullDefault: { label: "See the collection" }
- image
Photo in the centre tile, the one that grows to fill the hero.
stringDefault: "/demo/26.webp" - altstringDefault: "A rider and horse at full gallop, blurred with speed"
- video
Plays in the centre tile instead of the photo.
string - sideImages
The two photo tiles at the sides.
[string, string]Default: ["/demo/23.webp", "/demo/34.webp"] - revealHeading
Shown once the centre tile has filled the hero.
stringDefault: "Built for the long way round." - revealDescriptionstringDefault: "Every route is walked, ridden and rewritten by the people who publish it."
- stats
The first two also get tiles of their own.
{ value: number; suffix?: string; label: string }[]Default: DEFAULT_STATS
Show all 15 propsShow fewer
| showGlow Soft light that follows the pointer. | boolean | true |
| scrollDistance How far people scroll to open the centre tile, in hero heights. | number | 1.2 |
| minHeight Height from tablet width up, in px. | number | 720 |
- showGlow
Soft light that follows the pointer.
booleanDefault: true - scrollDistance
How far people scroll to open the centre tile, in hero heights.
numberDefault: 1.2 - minHeight
Height from tablet width up, in px.
numberDefault: 720
Collections
Use-case pages that compare Bento Hero with the other components that do a similar job.
npm dependencies
Installed for you by the shadcn CLI.
Bento Hero FAQ
- Does it scroll the page?
- It scrolls inside its own container, so the effect works anywhere on a page. When it reaches the end, scrolling carries on to the page.
- Do my photos need to be black and white?
- No. A greyscale filter is applied to every photo, so any picture fits the look.
- Can the centre tile be a video?
- Yes. Pass video and it plays in place of the photo, muted and looping.
- How far do people have to scroll?
- scrollDistance sets it, in hero heights. The default is 1.2.
- How does it look on phones?
- The tiles stack under the centre photo, and the same scroll opens it to fill the hero.