Skip to content

feat(component): ActivityLog — Paginated Activity Feed #92

@bntvllnt

Description

@bntvllnt

Summary

Paginated, date-grouped activity feed with operation type icons, filter buttons, and load-more pagination. Each entry shows an operation with timestamp, metadata, and cost. Supports filtering by operation type. The standard audit/activity log pattern for any product with trackable operations.

Proposed API

<ActivityLog
  entries={entries}
  groupBy="date"
  onLoadMore={handleLoadMore}
  hasMore={status === "CanLoadMore"}
  isLoading={isLoading}
  totalCount={entries.length}
>
  <ActivityLog.Filters
    options={[
      { label: "All", value: "all" },
      { label: "Chat", value: "chat", icon: MessageSquare },
      { label: "Workflow", value: "workflow", icon: Zap },
    ]}
    value={filter}
    onChange={setFilter}
  />
</ActivityLog>

// Custom entry renderer
<ActivityLog
  entries={entries}
  renderEntry={(entry) => (
    <ActivityLog.Entry
      icon={<OperationIcon type={entry.type} />}
      title={entry.title}
      timestamp={entry.createdAt}
      metadata={`${entry.model} · ${entry.inputTokens} in / ${entry.outputTokens} out`}
      value={formatCurrency(entry.cost)}
      subtitle={entry.threadTitle ? `Thread: "${entry.threadTitle}"` : undefined}
    />
  )}
/>

Requirements

  • Date-grouped entries: entries grouped by formatted date headers
  • Entry layout: icon + title + metadata left, timestamp right, value right
  • Optional subtitle per entry (e.g., thread name)
  • Filter bar: button group with active state (uses Button ghost/secondary variants)
  • Filter options: configurable array of { label, value, icon? }
  • "Load more" button when more pages available
  • Loading state: centered spinner
  • Empty state: icon + message + description (respects active filter)
  • Total count badge in header
  • Custom entry renderer via renderEntry prop
  • Date grouping via groupBy="date" (extensible to "week", "month")
  • Dark mode: bordered entries with hover state
  • Accessible: list/feed semantics, filter buttons as toolbar with aria-pressed

Layout

┌──────────────────────────────────────────────────┐
│  [All] [Chat] [Workflow] [Other]    42 operations│
│                                                  │
│  MAR 8, 2025                                     │
│  ┌────────────────────────────────────────────┐  │
│  │ 💬 Chat Response              $0.0034      │  │
│  │    gpt-4o · 1,200 in / 450 out   2:34 PM  │  │
│  │    Thread: "API Design"                    │  │
│  └────────────────────────────────────────────┘  │
│  ┌────────────────────────────────────────────┐  │
│  │ ⚡ AI Workflow                  $0.0012     │  │
│  │    claude-haiku · 200 in / 50 out  1:15 PM │  │
│  └────────────────────────────────────────────┘  │
│                                                  │
│  MAR 7, 2025                                     │
│  ┌────────────────────────────────────────────┐  │
│  │ 📄 Title Generation            $0.0002     │  │
│  │    gpt-4o-mini · 50 in / 10 out   11:20 AM│  │
│  └────────────────────────────────────────────┘  │
│                                                  │
│              [Load more]                         │
└──────────────────────────────────────────────────┘

Use Cases

  • AI platform usage journal / audit log
  • API call history with cost tracking
  • CI/CD pipeline execution log
  • Server event activity feed
  • Admin panel user action audit trail

Composes

  • Badge, Button

Origin

Extracted from UsageJournal, JournalEntry, JournalDayGroup, OperationFilter, JournalEmptyState, JournalLoadingState in apps/web-ai-os/app/account/usage/components/usage-journal.tsx in vllnt/vllnt monorepo.

Metadata

Metadata

Assignees

No one assigned

    Labels

    analyticsUsage analytics & reporting componentscomponentNew componentp2-mediumMedium priority — quality of life

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions