Activity Feed
In-app activity feeds — a timeline of events with avatars, action text and timestamps.
Preview
@props([
'title' => 'Audit log',
'events' => null,
])
@php
$events ??= [
['type' => 'created', 'message' => 'User account', 'entity' => 'alice@example.com', 'meta' => null, 'time' => '09:41:02'],
['type' => 'updated', 'message' => 'Role changed for', 'entity' => 'Bob Martin', 'meta' => 'admin', 'time' => '09:38:55'],
['type' => 'deleted', 'message' => 'Record removed:', 'entity' => 'Invoice #10482', 'meta' => null, 'time' => '09:35:20'],
['type' => 'exported', 'message' => 'Data export by', 'entity' => 'Carol Singh', 'meta' => 'csv', 'time' => '09:30:11'],
['type' => 'created', 'message' => 'New project', 'entity' => 'Q3 Campaign', 'meta' => null, 'time' => '09:22:44'],
['type' => 'updated', 'message' => 'Settings updated by', 'entity' => 'Dev Kapoor', 'meta' => 'billing', 'time' => '09:18:03'],
['type' => 'deleted', 'message' => 'Comment deleted on', 'entity' => 'Sprint planning', 'meta' => null, 'time' => 'Yesterday'],
['type' => 'exported', 'message' => 'Report generated by', 'entity' => 'Priya Nair', 'meta' => 'pdf', 'time' => 'Yesterday'],
];
$typeConfig = [
'created' => ['chip' => 'bg-primary/10 text-primary', 'badge' => 'default', 'label' => 'Created', 'icon' => 'M12 5v14M5 12h14'],
'updated' => ['chip' => 'bg-muted text-muted-foreground', 'badge' => 'secondary', 'label' => 'Updated', 'icon' => 'M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z'],
'deleted' => ['chip' => 'bg-destructive/10 text-destructive', 'badge' => 'destructive', 'label' => 'Deleted', 'icon' => 'M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2m3 0v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6'],
'exported' => ['chip' => 'bg-accent text-accent-foreground', 'badge' => 'outline', 'label' => 'Export', 'icon' => 'M12 3v12m0 0-4-4m4 4 4-4M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2'],
];
@endphp
<x-ui.section space="md" {{ $attributes }}>
<x-ui.container size="sm" gutter="sm">
<x-ui.card>
<div class="flex items-center justify-between border-b border-border px-6 py-4">
<h2 class="text-sm font-semibold leading-5">{{ __($title) }}</h2>
<div class="flex items-center gap-x-2">
<button type="button" class="inline-flex items-center gap-x-2 rounded-md px-2 py-2 text-xs font-medium text-muted-foreground ring-1 ring-inset ring-border hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-3" aria-hidden="true"><path d="M3 4h18M7 10h10M11 16h2" /></svg>
{{ __('Filter') }}
</button>
<button type="button" class="inline-flex items-center gap-x-2 rounded-md px-2 py-2 text-xs font-medium text-muted-foreground ring-1 ring-inset ring-border hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-3" aria-hidden="true"><path d="M12 3v12m0 0-4-4m4 4 4-4M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2" /></svg>
{{ __('Export') }}
</button>
</div>
</div>
<ol aria-label="{{ __('Audit log entries') }}">
@foreach ($events as $event)
@php $cfg = $typeConfig[$event['type']] ?? $typeConfig['updated']; @endphp
<li class="{{ ! $loop->first ? 'border-t border-border' : '' }} flex items-center gap-x-4 px-6 py-2">
<span class="inline-flex shrink-0 items-center justify-center rounded-md p-2 {{ $cfg['chip'] }}" title="{{ __($cfg['label']) }}">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="size-3" aria-hidden="true"><path d="{{ $cfg['icon'] }}" /></svg>
</span>
<p class="min-w-0 flex-1 truncate text-sm text-muted-foreground">{{ __($event['message']) }} <span class="font-medium text-foreground">{{ $event['entity'] }}</span></p>
@if (! empty($event['meta']))<x-ui.badge :variant="$cfg['badge']" size="sm" class="shrink-0">{{ $event['meta'] }}</x-ui.badge>@endif
<time class="shrink-0 font-mono text-xs text-muted-foreground">{{ $event['time'] }}</time>
</li>
@endforeach
</ol>
</x-ui.card>
</x-ui.container>
</x-ui.section>
Installation
php artisan ui:add blocks/activity-feed-compact
Registry contract
Install confidence
php artisan ui:add blocks/activity-feed-compact
writes only the generated targets below. The CLI validates each file hash before writing and
prompts before replacing local changes unless --force is used.
- Version
- 1.0.4
- License
- open
- Stability
- stable
- Contract
- v1
- Foundation
- ≥ 1.0.0
| Type | Generated target |
|---|---|
| blade | resources/views/blocks/activity-feed-compact.blade.php |
Registry dependencies
Package dependencies
composer: jml/brok:^0.2
Use with AI
A brief for your coding agent: what the block is, the install command, how to render it, its props and the rules. Copy it, or open a prompt about this block in an assistant.
# Brok UI block: Activity Feed Compact (`activity-feed-compact`)
A dense audit-log feed of colour-coded type rows with a message, optional meta badge and a monospace timestamp.
Brok UI is a Laravel Blade registry. `ui:add` copies this block into the app as plain Blade the app owns; it composes installed `<brok:*>` primitives and semantic design tokens.
## Install
```bash
php artisan ui:add blocks/activity-feed-compact
```
## Render it
```blade
<x-blocks.activity-feed-compact />
```
## Props
- `title` (string, default `Audit log`)
- `events` (mixed|null, default `null`)
## Use when
- Rendering a dense, colour-coded audit log of created, updated, deleted and exported events with a monospace timestamp.
- Giving the log filter and export controls above a compact, scannable list rather than a spaced timeline.
## Avoid when
- Use activity-feed-timeline or activity-feed-grouped for a friendlier, avatar-led activity feed instead of a dense audit log.
## Rules
- Render the installed block with `<x-blocks.activity-feed-compact />` and pass data through its props; edit the copied file only for structural changes.
- Keep the semantic design tokens (`bg-background`, `text-muted-foreground`); never swap in raw colour utilities.
- Keep the `data-slot` attributes and the logical (start/end) spacing so the markup still mirrors under `dir="rtl"`.
## Links
- Docs: https://brokui.dev/blocks/activity-feed-compact
- Registry JSON (files, props, contract): https://brokui.dev/r/open/blocks/activity-feed-compact.json
Working in Claude Code, Cursor or Codex? Give the agent the whole registry through the MCP server or the Brok UI skill.
Guidance
Use when
- Rendering a dense, colour-coded audit log of created, updated, deleted and exported events with a monospace timestamp.
- Giving the log filter and export controls above a compact, scannable list rather than a spaced timeline.
Avoid when
- Use activity-feed-timeline or activity-feed-grouped for a friendlier, avatar-led activity feed instead of a dense audit log.
Anti-patterns
- Do not replace semantic props with conflicting utility classes.
- Do not remove labels, focus styles, or state attributes.
Usage
Render the block as a component, passing data where useful:
<x-blocks.activity-feed-compact />
Built from primitives
This block composes installed <brok:*> primitives and semantic design
tokens only — it does not reimplement any primitive. Re-theme it (light, dark, admin, customer) by
editing CSS variables; flip the preview to RTL to confirm it mirrors.
Source
The exact, editable file ui:add writes
into your app. The preview above renders this same source — there are no preview-only blocks.
@props([
'title' => 'Audit log',
'events' => null,
])
@php
$events ??= [
['type' => 'created', 'message' => 'User account', 'entity' => 'alice@example.com', 'meta' => null, 'time' => '09:41:02'],
['type' => 'updated', 'message' => 'Role changed for', 'entity' => 'Bob Martin', 'meta' => 'admin', 'time' => '09:38:55'],
['type' => 'deleted', 'message' => 'Record removed:', 'entity' => 'Invoice #10482', 'meta' => null, 'time' => '09:35:20'],
['type' => 'exported', 'message' => 'Data export by', 'entity' => 'Carol Singh', 'meta' => 'csv', 'time' => '09:30:11'],
['type' => 'created', 'message' => 'New project', 'entity' => 'Q3 Campaign', 'meta' => null, 'time' => '09:22:44'],
['type' => 'updated', 'message' => 'Settings updated by', 'entity' => 'Dev Kapoor', 'meta' => 'billing', 'time' => '09:18:03'],
['type' => 'deleted', 'message' => 'Comment deleted on', 'entity' => 'Sprint planning', 'meta' => null, 'time' => 'Yesterday'],
['type' => 'exported', 'message' => 'Report generated by', 'entity' => 'Priya Nair', 'meta' => 'pdf', 'time' => 'Yesterday'],
];
$typeConfig = [
'created' => ['chip' => 'bg-primary/10 text-primary', 'badge' => 'default', 'label' => 'Created', 'icon' => 'M12 5v14M5 12h14'],
'updated' => ['chip' => 'bg-muted text-muted-foreground', 'badge' => 'secondary', 'label' => 'Updated', 'icon' => 'M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z'],
'deleted' => ['chip' => 'bg-destructive/10 text-destructive', 'badge' => 'destructive', 'label' => 'Deleted', 'icon' => 'M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2m3 0v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6'],
'exported' => ['chip' => 'bg-accent text-accent-foreground', 'badge' => 'outline', 'label' => 'Export', 'icon' => 'M12 3v12m0 0-4-4m4 4 4-4M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2'],
];
@endphp
<x-ui.section space="md" {{ $attributes }}>
<x-ui.container size="sm" gutter="sm">
<x-ui.card>
<div class="flex items-center justify-between border-b border-border px-6 py-4">
<h2 class="text-sm font-semibold leading-5">{{ __($title) }}</h2>
<div class="flex items-center gap-x-2">
<button type="button" class="inline-flex items-center gap-x-2 rounded-md px-2 py-2 text-xs font-medium text-muted-foreground ring-1 ring-inset ring-border hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-3" aria-hidden="true"><path d="M3 4h18M7 10h10M11 16h2" /></svg>
{{ __('Filter') }}
</button>
<button type="button" class="inline-flex items-center gap-x-2 rounded-md px-2 py-2 text-xs font-medium text-muted-foreground ring-1 ring-inset ring-border hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-3" aria-hidden="true"><path d="M12 3v12m0 0-4-4m4 4 4-4M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2" /></svg>
{{ __('Export') }}
</button>
</div>
</div>
<ol aria-label="{{ __('Audit log entries') }}">
@foreach ($events as $event)
@php $cfg = $typeConfig[$event['type']] ?? $typeConfig['updated']; @endphp
<li class="{{ ! $loop->first ? 'border-t border-border' : '' }} flex items-center gap-x-4 px-6 py-2">
<span class="inline-flex shrink-0 items-center justify-center rounded-md p-2 {{ $cfg['chip'] }}" title="{{ __($cfg['label']) }}">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="size-3" aria-hidden="true"><path d="{{ $cfg['icon'] }}" /></svg>
</span>
<p class="min-w-0 flex-1 truncate text-sm text-muted-foreground">{{ __($event['message']) }} <span class="font-medium text-foreground">{{ $event['entity'] }}</span></p>
@if (! empty($event['meta']))<x-ui.badge :variant="$cfg['badge']" size="sm" class="shrink-0">{{ $event['meta'] }}</x-ui.badge>@endif
<time class="shrink-0 font-mono text-xs text-muted-foreground">{{ $event['time'] }}</time>
</li>
@endforeach
</ol>
</x-ui.card>
</x-ui.container>
</x-ui.section>
Ownership & lifecycle
Owner, release state, review evidence and adoption for this item.
- Owner
- Platform UI (@JoshJML)
- Current version
-
1.0.4 - Status
- Stable
- License
-
open - Deprecation
- Not deprecated
- Contract
-
v1 - Foundation
-
≥ 1.0.0