A six-slot mosaic under a parenthetical eyebrow and a large heading, mixing full-bleed photo tiles with flat text tiles on muted and inverted surfaces, where the treatment belongs to the slot and every tile advances one story through a larger article pool on a timer, staggered 100 milliseconds apart so the refresh reads as a wave running left to right, pausing on hover, focus, hidden tabs, and reduced motion.
A blog listing section that lays a rolling newsroom into a fixed six-tile mosaic mixing full-bleed photo tiles with flat text tiles on muted and inverted surfaces. The treatment belongs to the slot rather than to the article, so on every tick each tile advances one story through a larger pool while the geometry stays put. The tiles do not turn over together: each one starts 100 ms after the tile before it, so the refresh reads as a wave running left to right.
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/blog51?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/blog51?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/blog51.tsx and its dependencies, including the Badge7 component it renders.
The installed file exports blog51Demo alongside the block: the exact props behind the preview above, including its pool of eighteen articles. Spread it to get a working mosaic in one line.
import { Blog51, blog51Demo } from "@/components/beste/block/blog51";
export default function Page() {
return <Blog51 {...blog51Demo} />;
}Then replace the demo with your own props. Pass more articles than there are tiles so the mosaic has somewhere to rotate to; six tiles against eighteen stories is what the demo uses.
import { Blog51 } from "@/components/beste/block/blog51";
export default function Page() {
return (
<Blog51
badge={{ label: "Press releases" }}
heading="From the Northwind newsroom"
description="Results, appointments, and reports from across the group."
intervalMs={5000}
items={[
{
image: { src: "/press/aragon.jpg", alt: "Battery cabinets in a storage hall" },
category: "Corporate",
title: "Aragon storage campus enters commercial operation",
date: "March 4, 2026",
author: { name: "Maria Santos", title: "Tech Lead" },
href: "/press/aragon-storage",
},
{
image: { src: "/press/q4.jpg", alt: "Quarterly figures on a screen" },
category: "Markets",
title: "Fourth-quarter revenue climbs 12 percent",
date: "February 26, 2026",
author: { name: "David Chen", title: "Backend Engineer" },
href: "/press/q4-revenue",
},
// ...more stories; the pool is what the tiles cycle through
]}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
badge | Badge | – | Badge7 parenthetical eyebrow above the heading |
heading | string | – | Section heading |
description | string | – | Muted supporting paragraph under the heading |
items | Article[] | [] | The story pool the six tiles cycle through |
intervalMs | number | – | Milliseconds between ticks; falls back to 5000 when omitted |
className | string | – | Extra classes merged onto the outer section element |
type Badge = {
label: string;
};
type Article = {
image: ArticleImage;
category: string;
title: string;
date: string;
author: Author;
href: string;
};
type ArticleImage = {
src: string;
alt: string;
};
type Author = {
name: string;
title?: string;
avatar?: { src: string; alt: string };
href?: string;
};Only author.name is rendered, in the tile byline. The optional title, avatar, and href fields on the author exist for shape parity with the other blog blocks and are not displayed here.
col-span-2 row-span-2 photo tile, slots 2 and 3 are single-cell photo tiles and slot 5 is a wide col-span-2 photo tile, while slot 1 is a tall row-span-2 bg-muted text tile and slot 4 is a wide col-span-2 inverted bg-foreground text tile. Because the articles move and the slots do not, a given story is rendered as a photograph in one position and as a flat text tile a few ticks later.items is the pool waiting its turn.(index + 1) % poolSize translation. Slots that start out distinct therefore stay distinct, so the same story can never occupy two tiles at once and no per-slot bookkeeping is needed. With the demo's eighteen articles the mosaic walks the whole pool and returns to its starting arrangement after eighteen ticks.i begins its fade at i * 100 ms and commits its new article 300 ms after that, so a full wave takes 800 ms and finishes well inside the default 5000 ms interval. Every timeout id is collected in one array that the effect cleanup clears, and because the effect re-runs on each tick that cleanup also fires before a fresh wave is queued, so an intervalMs shorter than the wave cannot orphan a timer or strand a tile at zero opacity.window.matchMedia("(prefers-reduced-motion: reduce)") and kept live through a change listener. The same guard suppresses rotation while the tab is hidden (tracked via visibilitychange), while a pointer is over the grid, and while any tile holds focus, so tabbing through the links pauses the mosaic for as long as focus stays inside.image supplied on an article currently sitting in slot 1 or 4 is not displayed. Give every article one anyway, since the rotation will move it into a photo slot.auto-rows-[11rem], md:auto-rows-[13rem]), so a swap can never reflow the layout, and titles are clamped per slot so a long headline cannot overflow its tile. No min-height reservations are needed for that reason.Link wrapping the whole tile with a visible focus ring, and the grid carries aria-live="off" so rotating content is never announced mid-tick. Photos have no hover treatment; the only hover motion is the ArrowUpRight nudge on the text tiles, guarded by motion-safe.blog50
A six-slot magazine mosaic with a parenthetical eyebrow and a large heading, pairing a dominant two-by-two tile with a tall tile, wide tiles, and unit tiles that each caption their photo over a graded scrim.
blog56
A six-slot photo mosaic under a parenthetical eyebrow and a large heading, where every tile is bound to one newsroom category so the grid doubles as a section map, with a ruled legend naming the sections above it.
blog53
A press office masonry wall under a parenthetical eyebrow and a large heading, mixing photo cards with image-free release cards on soft muted surfaces, each release card closing on a read-through line with a corner arrow.
blog48
A newsroom listing with a square eyebrow, a two-column heading band over a hairline rule, and four equally weighted stories as bordered cards, each linking through a hover-zoom image, a category kicker, a bold headline, a summary, and a byline pinned to the card foot.