Menu

Change language

GitHub repo

Activity Feed

blockproductivity

Record activity as a Timeline of avatar rows. Each row is spelled out inline — actor, verb, optional comment, relative time. Edit the rows after install; no items wrapper.

Installation

$npx uipkge-ng@latest add activity-feed
Manifest:https://uipkge.dev/r/angular/activity-feed.jsonInstalls to:src/app/components/blocks/activity-feed/

Variants

Loading interactive previews…

Files installed (2)

  • src/app/components/blocks/activity-feed/activity-feed.component.ts4.4 kB
    // Record activity as a Timeline of avatar rows. Each row is spelled out inline — actor,
    // verb, optional comment, relative time. Port of the React block 1:1.
    import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
    import { cn } from '@/lib/utils'
    import { UiAvatarComponent, UiAvatarFallbackComponent } from '@/ui/avatar/avatar.component'
    import { UiRelativeTimeComponent } from '@/ui/relative-time/relative-time.component'
    import { UiSectionCardComponent } from '@/ui/section-card/section-card.component'
    import {
      UiTimelineComponent,
      UiTimelineContentComponent,
      UiTimelineItemComponent,
      UiTimelineMediaComponent,
    } from '@/ui/timeline/timeline.component'
    
    @Component({
      changeDetection: ChangeDetectionStrategy.Eager,
      selector: 'ui-activity-feed, [ui-activity-feed]',
      standalone: true,
      // React renders the root SectionCard itself: the host stays out of layout and `class` goes to the root.
      host: { '[attr.class]': '"contents"' },
      imports: [
        UiAvatarComponent,
        UiAvatarFallbackComponent,
        UiRelativeTimeComponent,
        UiSectionCardComponent,
        UiTimelineComponent,
        UiTimelineContentComponent,
        UiTimelineItemComponent,
        UiTimelineMediaComponent,
      ],
      template: `
        <ui-section-card data-slot="activity-feed" [class]="rootClass" [title]="title" [description]="description">
          <ui-timeline>
            <ui-timeline-item status="success">
              <ui-timeline-media variant="avatar">
                <ui-avatar size="sm">
                  <ui-avatar-fallback size="sm" class="text-foreground">MC</ui-avatar-fallback>
                </ui-avatar>
              </ui-timeline-media>
              <ui-timeline-content>
                <p class="text-sm">
                  <span class="font-medium">Maya Chen</span>
                  <span class="text-muted-foreground"> approved the leave request</span>
                </p>
                <ui-relative-time date="2026-08-14T11:18:00.000Z" [now]="now" locale="en" class="mt-0.5 block text-xs" />
              </ui-timeline-content>
            </ui-timeline-item>
    
            <ui-timeline-item status="info">
              <ui-timeline-media variant="avatar">
                <ui-avatar size="sm">
                  <ui-avatar-fallback size="sm" class="text-foreground">OF</ui-avatar-fallback>
                </ui-avatar>
              </ui-timeline-media>
              <ui-timeline-content>
                <p class="text-sm">
                  <span class="font-medium">Omar Farid</span>
                  <span class="text-muted-foreground"> added a comment</span>
                </p>
                <p class="text-muted-foreground mt-1 text-sm">Coverage is confirmed for Thursday and Friday.</p>
                <ui-relative-time date="2026-08-14T10:04:00.000Z" [now]="now" locale="en" class="mt-0.5 block text-xs" />
              </ui-timeline-content>
            </ui-timeline-item>
    
            <ui-timeline-item status="muted">
              <ui-timeline-media variant="avatar">
                <ui-avatar size="sm">
                  <ui-avatar-fallback size="sm" class="text-foreground">PS</ui-avatar-fallback>
                </ui-avatar>
              </ui-timeline-media>
              <ui-timeline-content>
                <p class="text-sm">
                  <span class="font-medium">Priya Shah</span>
                  <span class="text-muted-foreground"> updated the title to “Q3 planning offsite”</span>
                </p>
                <ui-relative-time date="2026-08-13T16:40:00.000Z" [now]="now" locale="en" class="mt-0.5 block text-xs" />
              </ui-timeline-content>
            </ui-timeline-item>
    
            <ui-timeline-item status="muted">
              <ui-timeline-media variant="avatar">
                <ui-avatar size="sm">
                  <ui-avatar-fallback size="sm" class="text-foreground">LP</ui-avatar-fallback>
                </ui-avatar>
              </ui-timeline-media>
              <ui-timeline-content>
                <p class="text-sm">
                  <span class="font-medium">Leo Park</span>
                  <span class="text-muted-foreground"> opened this request</span>
                </p>
                <ui-relative-time date="2026-08-13T09:12:00.000Z" [now]="now" locale="en" class="mt-0.5 block text-xs" />
              </ui-timeline-content>
            </ui-timeline-item>
          </ui-timeline>
        </ui-section-card>
      `,
    })
    export class UiActivityFeedComponent {
      @Input() title = 'Activity'
      @Input() description = 'Latest changes on this record.'
      @Input('class') className?: string
    
      protected readonly now = new Date('2026-08-14T12:00:00.000Z')
    
      get rootClass(): string {
        return cn(this.className)
      }
    }
    
  • src/app/components/blocks/activity-feed/index.ts0.1 kB

Raw manifest:https://uipkge.dev/r/angular/activity-feed.json