Studio mosaic whose lead tile floats a mood-board media piece over a dotted field between its own eyebrow and statement, beside a photographic tile captioned on its scrim, an inverted figure tile, a soft quote tile and a bordered CTA tile.
A whole about page compressed into one screen. The lead tile frames a mood-board media piece between its own eyebrow and closing statement, and the tiles around it carry a photograph captioned on its scrim, one inverted figure, a quote and a bordered CTA. Nothing is captioned underneath a picture, so the grid holds together on a phone as well as on a desktop.
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/bento2?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/bento2?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/bento2.tsx, the media22 mood-board piece it frames in the lead tile, and the badge7 and button12 components it uses.
The installed file exports bento2Demo alongside the block: the exact props behind the preview above. Spread it to get a working bento in one line.
import { Bento2, bento2Demo } from "@/components/beste/block/bento2";
export default function Page() {
return <Bento2 {...bento2Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { Bento2 } from "@/components/beste/block/bento2";
import { Media22 } from "@/components/beste/piece/media22";
export default function Page() {
return (
<Bento2
badge={{ label: "The studio at a glance" }}
heading="Nine people, one floor, no account managers."
labels={{
mediaEyebrow: "On the wall this week",
mediaTitle: "Every project starts as a board before it starts as a file.",
}}
media={<Media22 label="Board 14" tiles={[{ src: "/board/one.jpg", alt: "Specimen" }]} />}
image={{ src: "/studio/floor.jpg", alt: "Studio interior", caption: "Rotterdam, since 2016" }}
figure={{ value: "72%", title: "Clients who come back" }}
quote={{
quote: "The only studio we have hired twice without running a pitch.",
name: "Ines Volkert",
role: "Head of Brand",
}}
cta={{ title: "Come and see the boards.", buttonLabel: "Meet the studio", href: "/studio" }}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
badge | { label: string } | – | Eyebrow label rendered as a Badge7 |
heading | string | – | Section heading above the grid |
media | ReactNode | – | Media object framed by the lead tile, usually a registry piece |
image | PhotoTile | – | Photographic tile captioned on its own scrim |
figure | FigureTile | – | Inverted dark figure tile |
quote | QuoteTile | – | Soft quote tile |
cta | CtaTile | – | Bordered tile holding a Button12 pill |
labels | Bento2Labels | {} | Fixed strings that are not content: the lead tile's eyebrow and statement |
className | string | – | Extra classes for the outer <section> |
type PhotoTile = { src: string; alt: string; caption: string };
type FigureTile = { value: string; title: string };
type QuoteTile = { quote: string; name: string; role: string };
type CtaTile = { title: string; buttonLabel: string; href: string };
type Bento2Labels = { mediaEyebrow?: string; mediaTitle?: string };media is a ReactNode, so any piece can sit in the lead tile: swap Media22 for a browser, editor or stats piece without touching the block.radial-gradient on currentColor at text-foreground/20, with no second fill and no border: the tile keeps one surface and the pattern follows the theme in light and dark. The eyebrow above and the statement below sit on the plain part of the tile.md:col-span-4 md:row-span-2 and the rows are md:auto-rows-[minmax(13rem,auto)], so tiles grow with their content instead of clipping it.text-background tokens because that surface is fixed rather than adaptive.md everything stacks in source order, with the lead tile holding a min-h-[420px] so the piece keeps room to breathe.bento4
Service mosaic whose lead tile floats a photo-strip media piece over a dotted field between its eyebrow and statement, beside a photographic tile captioned on its scrim, an inverted figure tile and three soft icon tiles.
bento7
Team mosaic where portraits carry their name and role inside the tile on a scrim, interleaved with an inverted quote tile and a wide soft tenure figure tile that closes the grid flush.
bento11
A six-column bento mixing a lead card whose image tile floats a live metrics panel, a soft statement tile, an inverted figure tile, a second asset tile carrying an uptime strip, a hairline inclusion list, and a captioned photograph.
bento3
Work mosaic on a six-column track mixing photographic tiles that carry their caption inside on a gradient scrim with a soft statement tile and an inverted figure tile, the lead project spanning four columns and two rows.