
Dense security audit log in a card: one timeline row per event with the actor in bold, a right-aligned time and a muted Geist Mono line of IP, key or device detail, plus an Export button.
blocks/feed/audit-log/index.tsx
import {
Timeline,
TimelineContent,
TimelineIndicator,
TimelineItem,
TimelineLabel,
TimelineTitle,
} from "@/components/editorial/timeline"
import { Button } from "@/components/ui/button"
import {
Card,
CardAction,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card"
// The copy: change text here, not in the markup.
const COPY = {
title: "Audit log",
body: "Security-relevant events on this workspace.",
cta: "Export",
} as const
const EVENTS = [
{
actor: "Lena Orvik",
action: "changed the billing email",
meta: "lena@orbcore.dev · 193.0.12.4",
time: "14:02",
},
{
actor: "Tomas Vey",
action: "created an API key",
meta: "ok_live_…9f2a · 10.4.0.18",
time: "13:47",
},
{
actor: "Ines Halloran",
action: "removed Elias Quill from Admins",
meta: "193.0.12.9",
time: "11:20",
},
{
actor: "System",
action: "rotated the signing secret",
meta: "scheduled",
time: "03:00",
},
{
actor: "Kofi Brandt",
action: "signed in with a new device",
meta: "macOS · Chrome · Lisbon",
time: "Yesterday 22:15",
},
{
actor: "Mira Sato",
action: "enabled two-factor sign-in",
meta: "193.0.12.2",
time: "Yesterday 09:31",
},
] as const
// Dense: one line per event, the detail in a muted mono line under it. The
// actor is the bold name, not a mark; the dot only places the row in time.
export default function AuditLog() {
return (
<Card className="mx-auto w-full max-w-md">
<CardHeader>
<CardTitle>{COPY.title}</CardTitle>
<CardDescription>{COPY.body}</CardDescription>
<CardAction>
<Button variant="outline" size="sm">
{COPY.cta}
</Button>
</CardAction>
</CardHeader>
<CardContent>
<Timeline className="[--timeline-lh:1.25rem]">
{EVENTS.map((e) => (
<TimelineItem key={e.action + e.time}>
<TimelineIndicator className="border-0 [&_[data-slot=timeline-dot]]:bg-muted-foreground/60" />
<TimelineContent className="pb-5">
<div className="flex items-baseline justify-between gap-3">
<TimelineTitle className="text-sm/5 font-normal">
<span className="font-medium">{e.actor}</span> {e.action}
</TimelineTitle>
<TimelineLabel className="shrink-0 tabular-nums">
{e.time}
</TimelineLabel>
</div>
<p className="mt-0.5 font-mono text-xs text-muted-foreground">
{e.meta}
</p>
</TimelineContent>
</TimelineItem>
))}
</Timeline>
</CardContent>
</Card>
)
}