
Two wide blog post rows, each with uppercase tags, a large title, excerpt, author, date, and read-more link beside an image, under a centered heading.
@shadcnblocks
block/blog8/blog8.tsx
import { cn } from "cn";
import { ArrowRight } from "lucide-react";
import { Card } from "@/components/ui/card";
interface BlogRowPost {
id?: string;
title: string;
summary?: string;
href?: string;
image?: Image;
logo?: Image;
team?: string;
category?: string;
tags?: string[];
date?: string;
readTime?: string;
author?: string;
role?: string;
avatar?: Image;
initials?: string;
cta?: string;
}
interface Image {
src: string;
alt: string;
srcDark?: string;
}
interface BlogRowProps {
heading: string;
description?: string;
posts: BlogRowPost[];
className?: string;
}
interface Blog8Props extends BlogRowProps {}
type Props = Partial<Blog8Props>;
const person1 = {
name: "Jack Walsh",
firstName: "Jack",
lastName: "Walsh",
initials: "JW",
email: "jack.walsh@example.com",
username: "jackwalsh",
role: "Product Designer",
company: "Cartwright",
location: "Brisbane, Australia",
avatar: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/avatars/avatar1.webp",
};
const person2 = {
name: "Ilze Pērkone",
firstName: "Ilze",
lastName: "Pērkone",
initials: "MK",
email: "iperkone@example.com",
username: "iperkone",
role: "Brand Director",
company: "Kivit",
location: "Rīga, Latvia",
avatar: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/avatars/avatar2.webp",
};
const person3 = {
name: "Vernon Desilets",
firstName: "Vernon",
lastName: "Desilets",
initials: "VD",
email: "vernod@example.com",
username: "vernod",
role: "Creative Director",
company: "Soho Logix",
location: "Paris, France",
avatar: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/avatars/avatar3.webp",
};
const person4 = {
name: "Lín Wàngshū",
firstName: "Lín",
lastName: "Wangshu",
initials: "LW",
email: "linwang4@example.com",
username: "liwang",
role: "Graphic Designer",
company: "Tenxcloud",
location: "Shanghai, China",
avatar: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/avatars/avatar4.webp",
};
const person5 = {
name: "Rajesh Bhatt",
firstName: "Rajesh",
lastName: "Bhatt",
initials: "RB",
email: "rajesh.bhatt@example.com",
username: "rajeshbhatt",
role: "UX Researcher",
company: "Mindtree",
location: "Mumbai, India",
avatar: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/avatars/avatar5.webp",
};
const person6 = {
name: "Jessica Cannon",
firstName: "Jessica",
lastName: "Cannon",
initials: "JC",
email: "jessica.cannon@example.com",
username: "jessicacannon",
role: "Data Analyst",
company: "Fidelity Investments",
location: "Boston, USA",
avatar: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/avatars/avatar6.webp",
};
const defaultProps: Blog8Props = {
heading: "Blog",
description: "Notes on design, product, and the work of building software.",
posts: [
{
id: "post-1",
title: "What changed in interface design this year",
summary:
"A look at the patterns that stuck, and the ones that quietly disappeared.",
href: "#",
image: {
src: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/blog-corporate/photo-1-16x9.jpg",
alt: "Colleagues working at a shared desk",
},
category: "Design",
tags: ["Design", "Product"],
date: "March 12, 2026",
readTime: "6 min",
author: person1.name,
role: person1.role,
avatar: {
src: person1.avatar,
alt: person1.name,
},
initials: person1.initials,
cta: "Read article",
logo: {
src: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/logos/fictional-company-logo-1.svg",
alt: person1.company,
},
team: person1.company,
},
{
id: "post-2",
title: "A practical guide to modern JavaScript",
summary:
"The language features we reach for, and the ones we leave alone.",
href: "#",
image: {
src: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/blog-corporate/photo-2-16x9.jpg",
alt: "A team gathered for a presentation",
},
category: "Technology",
tags: ["Technology", "Engineering"],
date: "March 4, 2026",
readTime: "8 min",
author: person2.name,
role: person2.role,
avatar: {
src: person2.avatar,
alt: person2.name,
},
initials: person2.initials,
cta: "Read article",
logo: {
src: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/logos/fictional-company-logo-2.svg",
alt: person2.company,
},
team: person2.company,
},
{
id: "post-3",
title: "Campaigns that still earn their keep",
summary:
"What held up after the novelty wore off, told with the numbers we kept.",
href: "#",
image: {
src: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/blog-corporate/photo-3-16x9.jpg",
alt: "A desk with a desktop computer",
},
category: "Marketing",
tags: ["Marketing", "Editorial"],
date: "February 24, 2026",
readTime: "5 min",
author: person3.name,
role: person3.role,
avatar: {
src: person3.avatar,
alt: person3.name,
},
initials: person3.initials,
cta: "Read article",
logo: {
src: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/logos/fictional-company-logo-3.svg",
alt: person3.company,
},
team: person3.company,
},
{
id: "post-4",
title: "How product teams write decisions down",
summary:
"A simple record of why a choice was made, written so the next person can find it.",
href: "#",
image: {
src: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/blog-corporate/photo-4-16x9.jpg",
alt: "Two colleagues talking by a window",
},
category: "Design",
tags: ["Design", "Product"],
date: "February 18, 2026",
readTime: "11 min",
author: person4.name,
role: person4.role,
avatar: {
src: person4.avatar,
alt: person4.name,
},
initials: person4.initials,
cta: "Read article",
logo: {
src: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/logos/fictional-company-logo-4.svg",
alt: person4.company,
},
team: person4.company,
},
{
id: "post-5",
title: "Accessible interfaces without a redesign",
summary:
"Small changes that make a page easier to use without a new visual system.",
href: "#",
image: {
src: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/blog-corporate/photo-5-16x9.jpg",
alt: "Three people collaborating around a laptop",
},
category: "Technology",
tags: ["Technology", "Engineering"],
date: "February 9, 2026",
readTime: "7 min",
author: person5.name,
role: person5.role,
avatar: {
src: person5.avatar,
alt: person5.name,
},
initials: person5.initials,
cta: "Read article",
logo: {
src: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/logos/fictional-company-logo-5.svg",
alt: person5.company,
},
team: person5.company,
},
{
id: "post-6",
title: "Shipping faster without skipping review",
summary: "How review stays in the path when the calendar gets tight.",
href: "#",
image: {
src: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/blog-corporate/photo-6-16x9.jpg",
alt: "A person writing on a glass wall",
},
category: "Marketing",
tags: ["Marketing", "Editorial"],
date: "January 28, 2026",
readTime: "9 min",
author: person6.name,
role: person6.role,
avatar: {
src: person6.avatar,
alt: person6.name,
},
initials: person6.initials,
cta: "Read article",
logo: {
src: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/logos/fictional-company-logo-6.svg",
alt: person6.company,
},
team: person6.company,
},
{
id: "post-7",
title: "Measuring what a launch actually did",
summary:
"The questions we ask a week later, once the launch post has gone quiet.",
href: "#",
image: {
src: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/blog-corporate/photo-7-16x9.jpg",
alt: "Colleagues talking in a warm-lit office",
},
category: "Design",
tags: ["Design", "Product"],
date: "January 19, 2026",
readTime: "4 min",
author: person1.name,
role: person1.role,
avatar: {
src: person1.avatar,
alt: person1.name,
},
initials: person1.initials,
cta: "Read article",
logo: {
src: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/logos/fictional-company-logo-1.svg",
alt: person1.company,
},
team: person1.company,
},
{
id: "post-8",
title: "The case for fewer tools",
summary: "Fewer dashboards, fewer logins, and a clearer week.",
href: "#",
image: {
src: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/blog-corporate/photo-8-16x9.jpg",
alt: "People talking at an office gathering",
},
category: "Technology",
tags: ["Technology", "Engineering"],
date: "January 8, 2026",
readTime: "12 min",
author: person2.name,
role: person2.role,
avatar: {
src: person2.avatar,
alt: person2.name,
},
initials: person2.initials,
cta: "Read article",
logo: {
src: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/logos/fictional-company-logo-2.svg",
alt: person2.company,
},
team: person2.company,
},
{
id: "post-9",
title: "Photography, type, and the quiet page",
summary: "How pictures and type share a page without competing.",
href: "#",
image: {
src: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/blog-corporate/photo-9-16x9.jpg",
alt: "A team meeting around a high table",
},
category: "Marketing",
tags: ["Marketing", "Editorial"],
date: "December 16, 2025",
readTime: "6 min",
author: person3.name,
role: person3.role,
avatar: {
src: person3.avatar,
alt: person3.name,
},
initials: person3.initials,
cta: "Read article",
logo: {
src: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/logos/fictional-company-logo-3.svg",
alt: person3.company,
},
team: person3.company,
},
{
id: "post-10",
title: "Notes on performance budgets",
summary: "A budget for weight, and what we cut when a page misses it.",
href: "#",
image: {
src: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/blog-corporate/photo-10-16x9.jpg",
alt: "A person working at a desktop computer",
},
category: "Design",
tags: ["Design", "Product"],
date: "December 4, 2025",
readTime: "8 min",
author: person4.name,
role: person4.role,
avatar: {
src: person4.avatar,
alt: person4.name,
},
initials: person4.initials,
cta: "Read article",
logo: {
src: "https://cdn.shadcnblocks.com/shadcnblocks/image-set/modern/logos/fictional-company-logo-4.svg",
alt: person4.company,
},
team: person4.company,
},
],
};
const MAX_POSTS = 2;
const Blog8 = (props: Props) => {
const { heading, description, posts, className } = {
...defaultProps,
...props,
};
const items = (posts ?? []).slice(0, MAX_POSTS);
return (
<section className={cn("py-32", className)}>
<div className="container mx-auto">
<div className="flex flex-col items-center gap-12">
<header className="flex flex-col items-center gap-4 text-center">
<h2 className="max-w-3xl text-3xl font-semibold tracking-tight text-balance md:text-4xl lg:text-5xl">
{heading}
</h2>
<p className="max-w-2xl text-lg font-medium text-pretty text-muted-foreground md:text-xl">
{description}
</p>
</header>
<div className="flex w-full flex-col gap-16">
{items.map((post, index) => (
<Card
key={post.id ?? index}
className="w-full gap-0 border-0 bg-transparent p-0 py-0 shadow-none ring-0"
>
<div className="grid gap-y-6 sm:grid-cols-2 sm:gap-x-5 md:items-center md:gap-x-8 lg:gap-x-12">
<div className="flex flex-col gap-4">
<div className="flex flex-wrap gap-3 text-xs font-medium tracking-wide text-muted-foreground uppercase md:gap-5 lg:gap-6">
{(post.tags ?? []).map((tag) => (
<span key={tag}>{tag}</span>
))}
</div>
<h3 className="text-xl font-semibold tracking-tight text-balance md:text-2xl lg:text-3xl">
<a
href={post.href}
target="_blank"
className="underline-offset-4 hover:underline focus-visible:underline focus-visible:outline-none"
>
{post.title}
</a>
</h3>
<p className="text-base leading-relaxed text-pretty text-muted-foreground">
{post.summary}
</p>
<div className="flex flex-wrap items-center gap-x-2 gap-y-1 text-sm">
<span className="font-medium text-foreground">
{post.author}
</span>
<span
aria-hidden="true"
className="text-muted-foreground/40"
>
·
</span>
<time className="text-muted-foreground tabular-nums">
{post.date}
</time>
</div>
<a
href={post.href}
target="_blank"
className="group/cue inline-flex items-center gap-1.5 text-sm font-medium underline-offset-4 hover:underline"
>
Read more
<ArrowRight className="size-4 text-muted-foreground transition-colors group-hover/cue:text-foreground" />
</a>
</div>
<div className="order-first sm:order-last">
<a
href={post.href}
tabIndex={-1}
aria-hidden="true"
target="_blank"
className="block overflow-hidden rounded-xl bg-muted"
>
<img
src={post.image?.src}
alt={post.image?.alt ?? ""}
className="aspect-16/9 h-full w-full object-cover transition-opacity duration-300 hover:opacity-90"
/>
</a>
</div>
</div>
</Card>
))}
</div>
</div>
</div>
</section>
);
};
export { Blog8 };

































