Activity Feed

Chronological event log with computed relative timestamps.

Live Demo

No events yet.

Source

HTML + JavaScript
<div data-component="activity-feed">
    <button data-action="addDeploy">+ Deploy</button>
    <button data-action="addAlert">+ Alert</button>

    <div data-list="events">
        <template>
            <div class="feed-item">
                <div data-bind-class="'feed-dot feed-dot-' + type"></div>
                <div>
                    <div data-bind="message"></div>
                    <div data-bind="relativeTime"></div>
                </div>
            </div>
        </template>
    </div>
</div>

<script>
wildflower.component('activity-feed', {
    state: {
        events: [
            { type: 'deploy', message: 'Deployed auth-service v2.4.1', timestamp: Date.now() - 120000 },
            { type: 'info', message: 'Config updated for staging', timestamp: Date.now() - 300000 },
            { type: 'alert', message: 'CPU usage above 80% on node-3', timestamp: Date.now() - 600000 },
            { type: 'error', message: 'Failed health check on db-replica-2', timestamp: Date.now() - 3600000 }
        ]
    },
    computed: {
        relativeTime(m) {
            const diff = Date.now() - m.timestamp;
            if (diff < 60000) return 'just now';
            if (diff < 3600000) return Math.floor(diff / 60000) + 'm ago';
            return Math.floor(diff / 3600000) + 'h ago';
        }
    },
    addDeploy() {
        this.events.unshift({
            type: 'deploy', message: 'Deployed api-gateway v1.' + Math.floor(Math.random()*20),
            timestamp: Date.now()
        });
    },
    addAlert() {
        this.events.unshift({
            type: 'alert', message: 'Memory spike on worker-' + Math.floor(Math.random()*8),
            timestamp: Date.now()
        });
    },
    clearFeed() { this.events = []; }
});
</script>

Key Points

  • data-bind-class="'feed-dot feed-dot-' + type" builds a class string from the event's type, mapping to a CSS color per event kind
  • Item-level computed relativeTime formats each event's timestamp relative to now
  • unshift() adds new events to the top of the list. The reactive proxy handles it
  • data-show="events.length === 0" shows an empty state when the feed is cleared