The full ledger of who did what, when and from where — sign-ins, permission changes, exports, deletes. Filter by text, actor, action and severity, expand an event for its field diff, JSON diff and raw payload, and scroll thousands of rows: long logs are virtualized while keeping native table semantics.
| Details | Time | Actor | Action | Target | Source |
|---|---|---|---|---|---|
| Ayşe KayaUser | Changed roleWarninguser.role.updated | Daniel BrooksUser · usr_482 | 88.230.14.7Istanbul, TR | ||
| Mehmet YılmazUser | Disabled two-factorCriticalauth.mfa.disabled | Mehmet YılmazUser · usr_311 | 176.88.40.211Ankara, TR | ||
| Zapier syncAPI key | Created contactcontact.created | Jane CooperContact · con_1209 | 54.86.50.139Ashburn, US | ||
| Daniel BrooksUser | Updated dealdeal.updated | Northwind renewal 2027Deal · deal_118 | 88.230.14.9Istanbul, TR | ||
| Nightly exportSystem | Exported dataWarningexport.created | All contacts (CSV · 12,408 rows)Export · exp_77 | — | ||
| İlker ŞahinUser | Deleted postpost.deleted | Summer menu launch (draft)Post · post_77 | 95.70.180.3Izmir, TR | ||
| UnknownSystem | Failed sign-inCriticalauth.login.failed | daniel.brooks@vamos.istUser · usr_482 | 185.220.101.44Frankfurt, DE | ||
| Ayşe KayaUser | Created API keyapiKey.created | Zapier syncApiKey · key_zap_02 | 88.230.14.7Istanbul, TR |
Installation
The whole kit as one package — get updates by bumping the version. Add the styles to globals.css: @import "@vamos-ui/react/styles.css";
Usage
import { AuditLog } from "@vamos-ui/react";
<AuditLog
events={events}
actionLabels={{ "user.role.updated": "Changed role", "export.created": "Exported data" }}
notice="Showing the last 90 days"
hasMore={hasMore}
onLoadMore={fetchOlder}
/>Rows expand with a labelled button (aria-expanded + aria-controls). Raw JSON sits in a focusable <pre> with a copy button. No row, header or tooltip is blurred in glass mode.
Examples
Event detail
Field or JSON diff of the change, ids with copy buttons, client, and the raw event.
Changes
| Field | Before | After |
|---|---|---|
| RoleChanged | Admin | |
| PermissionsChanged | posts.write, users.manage, billing.view |
Details
- Event ID
- evt_8f21a0
- Request ID
- req_9f2c41d7
- IP address
- 88.230.14.7
- Client
- Chrome 131 on macOS 15
- Reason
- Covering for team lead during leave
Server mode, 2,000 events
manualFiltering + onFiltersChange for your API; rowCount gives "250 of 2,000"; scrolling near the end calls onLoadMore.
| Details | Time | Actor | Action | Target | Source |
|---|
One record's history
variant="timeline" renders into Activity timeline with the field diff as the body.
- Ayşe Kaya changed role · Daniel Brooks
Field Before After RoleChanged EditorAdmin PermissionsChanged posts.writeposts.write, users.manage, billing.view - Unknown failed sign-in · daniel.brooks@vamos.ist
API
AuditLog
| Prop | Type | Default |
|---|---|---|
eventsEvents, newest first. | AuditEvent[] | — |
actionLabels"user.role.updated" → "Changed role". Missing codes are humanized. | Record<string, string> | — |
changeFieldsLabels and formats for the change diff. | FieldDiffField[] | — |
filters / defaultFilters / onFiltersChange{ q, actorId, action, severity } — controlled or not. | AuditFilters / … / (filters) => void | — |
manualFilteringServer mode: events are already filtered. | boolean | false |
rowCountServer total for "50 of 12,408 events". | number | — |
showFiltersBuilt-in filter row. | boolean | true |
toolbarExtra filters (a Date range picker). | ReactNode | — |
noticeRetention or scope notice. | ReactNode | — |
onExportExport button with the visible events. | (events) => void | — |
hasMore / onLoadMoreInfinite scroll plus a "Load older events" button. | boolean / () => void | Promise<void> | — |
loadingBusy indicator in the summary. | boolean | false |
heightScroll viewport height. | string | "32rem" |
virtualizeAfterVirtualize above this many events. | number | 80 |
variantFull ledger or a compact record feed. | "table" | "timeline" | "table" |
labelsAll built-in strings. | Partial<AuditLogLabels> | — |
AuditEvent
| Prop | Type | Default |
|---|---|---|
id / atIdentity and time. | string / ISO instant | — |
actorWho did it. | { id; name; type: "user" | "api-key" | "system"; avatar? } | — |
actionDotted code; filtering by "user" matches "user.*". | string | — |
targetWhat it was done to. | { type; id; label? } | — |
ip / location / userAgentWhere from (mono, left-to-right). | string | — |
changesField diff in the detail. | { before; after } | — |
metadatarequestId gets a copy row; the rest is listed. | Record<string, unknown> | — |
severityBadge and edge marker. | "info" | "warning" | "critical" | "info" |
Parts and helpers
| Prop | Type | Default |
|---|---|---|
AuditEventDetailThe expanded content on its own (drawer, page). | { event, changeFields } | — |
filterAuditEvents(events, filters, locale?, actionLabels?)The local filter, also usable on the server. | AuditEvent[] | — |