Skip to content
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

  • AK
    Asha Kulkarni marked INV-1042 as paid · ₹48,500
    2 min ago
  • RS
    Rohan Shah commented on Website redesign
    Homepage copy is approved. Can we move the launch to Monday?
    1 hour ago
  • MN
    Meera Nair booked Deep clean · 2BHK for Sat, 10:00
    Yesterday at 18:42
  • You
    You sent payment reminders to 3 customers
    Mon, 13 Oct
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.