
Workspace activity card built on ActivityFeedCard: a large event count, a timeline of deploys, merges and comments with one highlighted event, a 48-hour summary row and a full-width View all link.
blocks/feed/activity-feed/index.tsx
import { cn } from "cn"
import {
ActivityFeedCard,
type ActivityFeedEvent,
} from "@/components/activity/activity-feed-card"
import { buttonVariants } from "@/components/ui/button"
// The copy: change text here, not in the markup.
const COPY = {
title: "Activity",
body: "What changed across the workspace.",
count: "events",
window: "Last 48 hours",
latest: "Latest",
cta: "View all activity",
} as const
const EVENTS: ActivityFeedEvent[] = [
{
id: 1,
actor: "Lena Orvik",
action: "deployed",
target: "api-gateway",
time: "2h",
featured: true,
},
{
id: 2,
actor: "Tomas Vey",
action: "commented on",
target: "#482",
time: "3h",
comment:
"Looks right to me. One small note on the error handling, then merge.",
},
{
id: 3,
actor: "Ines Halloran",
action: "merged",
target: "rate-limiter",
time: "5h",
},
{
id: 4,
actor: "Kofi Brandt",
action: "tagged",
target: "v2.4.0",
time: "1d",
},
{
id: 5,
actor: "Mira Sato",
action: "closed",
target: "#311",
time: "1d",
comment: "Fixed by the latest deploy. It no longer happens on staging.",
},
{
id: 6,
actor: "Elias Quill",
action: "joined the workspace",
time: "2d",
},
]
export default function ActivityFeed() {
return (
<ActivityFeedCard
className="mx-auto w-full max-w-sm"
title={COPY.title}
description={COPY.body}
events={EVENTS}
countLabel={COPY.count}
summary={{
period: COPY.window,
latest: (
<>
{COPY.latest} {EVENTS[0].time}
</>
),
}}
actions={
<a
href="#"
data-slot="button"
className={cn(
buttonVariants({ variant: "secondary", size: "lg" }),
"w-full"
)}
>
{COPY.cta}
</a>
}
/>
)
}