All Taste components
Data display
Activity feed
Recent events with who did what and when, newest first, with unread items marked.
avatar · event icon · quoted comment · unread dot · relative time
- AKAsha Kulkarni marked INV-1042 as paid · ₹48,500
- RSRohan Shah commented on Website redesignHomepage copy is approved. Can we move the launch to Monday?
- MNMeera Nair booked Deep clean · 2BHK for Sat, 10:00
- YouYou sent payment reminders to 3 customers
import { Check, Clock } from "lucide-react";
type Event = {
id: string;
who: string;
initials: string;
action: React.ReactNode;
when: string;
quote?: string;
kind?: "paid" | "booking";
unread?: boolean;
};
const badge = {
paid: { icon: Check, className: "bg-success text-bg" },
booking: { icon: Clock, className: "bg-info text-bg" },
};
export function ActivityFeed({ events }: { events: Event[] }) {
return (
<ul aria-label="Recent activity" className="w-full max-w-[460px] divide-y divide-border">
{events.map((e) => {
const b = e.kind ? badge[e.kind] : null;
return (
<li key={e.id} className="flex gap-3 py-3">
<span className="relative shrink-0">
<span className="grid size-9 place-items-center rounded-full bg-primary-soft text-[13px] font-medium text-primary-soft-fg">{e.initials}</span>
{b && (
<span className={"absolute -bottom-[3px] -right-[3px] grid size-4 place-items-center rounded-full ring-2 ring-bg " + b.className}>
<b.icon className="size-2.5" aria-hidden />
</span>
)}
</span>
<div className="min-w-0 flex-1 text-[13.5px] leading-snug text-fg-muted">
<span className="font-medium text-fg">{e.who}</span> {e.action}
{e.quote && (
<p className="mt-2 rounded-r border-l-2 border-border-strong bg-surface px-3 py-2 text-fg">{e.quote}</p>
)}
<p className="mt-0.5 text-[12.5px] text-fg-subtle">{e.when}</p>
</div>
{e.unread && <span className="mt-1.5 size-2 shrink-0 rounded-full bg-primary" aria-label="Unread" />}
</li>
);
})}
</ul>
);
}
The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.