Skip to content

Activity feed

A chronological “who did what, when” list: an avatar per entry, the actor’s name in the sentence, and a muted timestamp underneath. A thin vertical line connects the avatars into a timeline, drawn only between entries so it stops at the last one. The action is a ReactNode, so you can bold or link the object that was acted on.

'use client';
import type { ReactNode } from 'react';
import { Avatar, Flex, Stack, Text } from '@helix-ui/core';
export interface ActivityItem {
id: string;
actor: { name: string; initials: string; avatarUrl?: string };
action: ReactNode;
timestamp: string;
}
export function ActivityFeed({ items }: { items: ActivityItem[] }) {
return (
<Stack gap={0}>
{items.map((item, i) => (
<Flex key={item.id} gap={3} align="start">
<Stack align="center" gap={2} style={{ alignSelf: 'stretch' }}>
<Avatar
size="sm"
fallback={item.actor.initials}
src={item.actor.avatarUrl}
alt={item.actor.name}
/>
{i < items.length - 1 ? (
<div
style={{
flex: 1,
width: 2,
minHeight: 20,
background: 'var(--helix-ui-color-border-default)',
}}
aria-hidden
/>
) : null}
</Stack>
<Stack gap={1} style={{ paddingBottom: 'var(--helix-ui-space-5)' }}>
<Text size="sm">
<Text as="span" weight="semibold">
{item.actor.name}
</Text>{' '}
{item.action}
</Text>
<Text size="xs" tone="muted">
{item.timestamp}
</Text>
</Stack>
</Flex>
))}
</Stack>
);
}

Usage

<ActivityFeed
items={[
{
id: '1',
actor: { name: 'Sara Tang', initials: 'ST' },
action: (
<>
merged{' '}
<Text as="span" weight="medium">
#482
</Text>{' '}
into main
</>
),
timestamp: '2 minutes ago',
},
{
id: '2',
actor: { name: 'Diego Ruiz', initials: 'DR' },
action: 'commented on the release checklist',
timestamp: '18 minutes ago',
},
{
id: '3',
actor: { name: 'Amara Okafor', initials: 'AO' },
action: 'closed the milestone',
timestamp: '1 hour ago',
},
]}
/>

Notes

  • Timestamps are pre-formatted strings — format them upstream (relative or absolute) so this block stays presentational.
  • For long feeds, paginate or cap the list; a timeline is for the recent past, not an audit log.