SolanaUISolanaUI

Activity Feed

A compact event list for displaying recent activity like swaps, trades, and transfers

Bought SOL
Bought SOLHdg...248
100 SOL2 minutes ago
Sold USDC
Sold USDC9dV...8hJ
5,000 USDC8 minutes ago
Bought BONK
Bought BONK3kY...2wB
2.4M BONK15 minutes ago
import { ActivityFeed } from "@/components/sol/activity-feed";

const SOL_ICON =
  "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/So11111111111111111111111111111111111111112/logo.png";

export function ActivityFeedDemo() {
  return (
    <ActivityFeed
      items={[
        {
          icon: SOL_ICON,
          title: "Bought SOL",
          description: "Hdg...248",
          timestamp: new Date(Date.now() - 2 * 60 * 1000),
          value: "100 SOL",
        },
      ]}
    />
  );
}

Installation

pnpm dlx shadcn@latest add @solanaui/activity-feed
npx shadcn@latest add @solanaui/activity-feed
yarn dlx shadcn@latest add @solanaui/activity-feed

Usage

<ActivityFeed
  items={[
    {
      icon: SOL_ICON,
      title: "Bought SOL",
      description: "Hdg...248",
      timestamp: new Date(Date.now() - 2 * 60 * 1000),
      value: "100 SOL",
    },
  ]}
/>

Source Code

import { formatDistanceToNow } from "date-fns";import { TokenIcon } from "@/registry/sol/token-icon";import { cn } from "@/lib/utils";interface ActivityFeedProps {  items: {    icon?: string;    title: string;    description?: string;    timestamp: Date;    value?: string;  }[];  className?: string;}const ActivityFeed = ({ items, className }: ActivityFeedProps) => {  if (items.length === 0) {    return (      <div className={cn("text-center py-8 text-muted-foreground", className)}>        No recent activity      </div>    );  }  return (    <div className={cn("flex flex-col", className)}>      {items.map((item, i) => (        <div          key={`${item.title}-${i}`}          className={cn(            "flex items-center gap-3 py-3 px-1",            i < items.length - 1 && "border-b",          )}        >          {item.icon && (            <TokenIcon              src={item.icon}              alt={item.title}              width={32}              height={32}            />          )}          <div className="flex flex-col flex-1 min-w-0">            <span className="text-sm font-medium truncate">{item.title}</span>            {item.description && (              <span className="text-xs text-muted-foreground truncate">                {item.description}              </span>            )}          </div>          <div className="flex flex-col items-end shrink-0">            {item.value && (              <span className="text-sm font-medium">{item.value}</span>            )}            <span className="text-xs text-muted-foreground">              {formatDistanceToNow(item.timestamp, { addSuffix: true })}            </span>          </div>        </div>      ))}    </div>  );};export type { ActivityFeedProps };export { ActivityFeed };