A compact actor and action feed with timestamps and an empty state.
Alex approved the design review
System published the preview build
Sam updated the release notes
import { ActivityFeed } from "@/components/ballmac/activity-feed"
export default function ActivityFeedDemo() {
return (
<ActivityFeed
className="w-full max-w-sm"
items={[
{
id: "a",
actor: "Alex",
action: "approved",
subject: "the design review",
timestamp: "Just now",
mark: "AL",
},
{
id: "b",
actor: "System",
action: "published",
subject: "the preview build",
timestamp: "18 minutes ago",
mark: "✓",
},
{
id: "c",
actor: "Sam",
action: "updated",
subject: "the release notes",
timestamp: "Yesterday",
mark: "SA",
},
]}
/>
)
}Installation
$ pnpm dlx shadcn@latest add @ballmac/activity-feedAdd the Ballmac items it builds on.
$ pnpm dlx shadcn@latest add @ballmac/i18nCopy the source into your project.
components/ballmac/activity-feed.tsx// Ballmac UI: Activity Feed. https://ui.ballmac.com/components/activity-feed "use client" import * as React from "react" import { cn } from "@/lib/utils" import { useMessages } from "@/lib/ballmac/i18n" type Activity = { /** Stable item identifier. */ id: string /** Person or system responsible. */ actor: string /** Action description. */ action: string /** Accessible timestamp. */ timestamp: string /** ISO datetime for machine readers. */ dateTime?: string /** Optional context such as a project or file. */ subject?: string /** Optional initials or symbol. */ mark?: string } type ActivityFeedProps = React.ComponentProps<"ol"> & { /** Ordered activity entries. */ items: Activity[] /** Message when the feed has no entries. */ emptyMessage?: string } function ActivityFeed({ className, items, emptyMessage, ...props }: ActivityFeedProps) { const msg = useMessages() emptyMessage ??= msg("activity-feed.emptyMessage", "No activity yet") return ( <ol data-slot="activity-feed" className={cn( "bg-card min-w-0 rounded-xl border border-border px-4", className, )} {...props} > {items.length ? ( items.map((item) => ( <li key={item.id} data-slot="activity-feed-item" className="flex min-w-0 gap-3 border-b border-border py-4 last:border-b-0" > <span data-slot="activity-feed-mark" aria-hidden="true" className="bg-primary/10 text-primary flex size-9 shrink-0 items-center justify-center rounded-full text-xs font-semibold" > {item.mark ?? item.actor.slice(0, 2).toUpperCase()} </span> <div className="min-w-0 flex-1"> <p className="text-sm leading-relaxed"> <strong className="font-medium">{item.actor}</strong>{" "} {item.action} {item.subject && ( <> {" "} <span className="font-medium">{item.subject}</span> </> )} </p> <time dateTime={item.dateTime} className="text-muted-foreground mt-1 block text-xs" > {item.timestamp} </time> </div> </li> )) ) : ( <li data-slot="activity-feed-empty" className="text-muted-foreground py-8 text-center text-sm" > {emptyMessage} </li> )} </ol> ) } export { ActivityFeed, type ActivityFeedProps, type Activity }Update the import paths to match your project setup.
Usage
import { ActivityFeed } from "@/components/ballmac/activity-feed"The full example is in the Code tab above.
Examples
States and variants
- Changes to this workspace will appear here.
import { ActivityFeed } from "@/components/ballmac/activity-feed"
export default function ActivityFeedStates() {
return (
<ActivityFeed
className="w-full max-w-sm"
items={[]}
emptyMessage="Changes to this workspace will appear here."
/>
)
}API reference
| Prop | Type | Default |
|---|---|---|
items*Ordered activity entries. | Activity[] | — |
emptyMessageMessage when the feed has no entries. | string | — |
Also accepts the standard attributes of its root element.
Accessibility
| Key | Action |
|---|---|
| None | Static content is announced with semantic structure |
Use with AI
A compact actor and action feed with timestamps and an empty state. With the shadcn MCP server set up (guide), ask your agent:
Add the Ballmac UI Activity Feed (@ballmac/activity-feed) to this project with the shadcn MCP, then use it where it fits.
Use it for
- Show recent changes made by people or the system
Not for
- Use Timeline for milestone progression
Registry JSON: https://ui.ballmac.com/r/activity-feed.json
Credits
Free to use in personal and commercial projects.
- npm
- None
- Registry
- @ballmac/i18nshadcn/utils
Pairs well with
Timeline
A composable sequence of milestones with current and complete states, dates, and connectors.
Audio Player
A podcast-style audio player: play and pause, skip back and forward, a scrubber with chapter ticks, a named current chapter and a speed control. Works with a real file or as a silent demo.
Avatar Circles
Overlapping avatars that spread on hover, lift individually with a name and role tooltip, show presence, fall back to initials and end in a +N count that can be a button.
Avatar Stack
An accessible compact row of people with initials, image support, and an overflow count.