Audit Log

Record of system/user actions.

Security audit trail
ActorActionTargetTimestamp
A. Whitfieldusr_8841 role.updated acct_2210
M. Duarteusr_1190 login.failed usr_1190
S. Novakusr_4402 record.deleted rec_7734
A. Whitfieldusr_8841 permission.granted team_09
J. Kocherusr_2255 export.completed rpt_5561

html

<table class="audit audit--striped" style="--accent:#241430;">
  <caption class="audit__caption">Security audit trail</caption>
  <thead>
    <tr><th scope="col">Actor</th><th scope="col">Action</th><th scope="col">Target</th><th scope="col">Timestamp</th></tr>
  </thead>
  <tbody data-rows="4">
    <tr>
      <th scope="row">A. Whitfield<span class="audit__id audit__id--mono">usr_8841</span></th>
      <td>role.updated</td>
      <td class="audit__id audit__id--mono">acct_2210</td>
      <td><time datetime="2026-08-18T08:12:00Z">18 Aug, 08:12</time></td>
    </tr>
    <tr>
      <th scope="row">M. Duarte<span class="audit__id audit__id--mono">usr_1190</span></th>
      <td>login.failed</td>
      <td class="audit__id audit__id--mono">usr_1190</td>
      <td><time datetime="2026-08-18T07:58:00Z">18 Aug, 07:58</time></td>
    </tr>
    <tr>
      <th scope="row">S. Novak<span class="audit__id audit__id--mono">usr_4402</span></th>
      <td>record.deleted</td>
      <td class="audit__id audit__id--mono">rec_7734</td>
      <td><time datetime="2026-08-17T22:41:00Z">17 Aug, 22:41</time></td>
    </tr>
    <tr>
      <th scope="row">A. Whitfield<span class="audit__id audit__id--mono">usr_8841</span></th>
      <td>permission.granted</td>
      <td class="audit__id audit__id--mono">team_09</td>
      <td><time datetime="2026-08-17T19:05:00Z">17 Aug, 19:05</time></td>
    </tr>
    <tr>
      <th scope="row">J. Kocher<span class="audit__id audit__id--mono">usr_2255</span></th>
      <td>export.completed</td>
      <td class="audit__id audit__id--mono">rpt_5561</td>
      <td><time datetime="2026-08-17T14:30:00Z">17 Aug, 14:30</time></td>
    </tr>
  </tbody>
</table>
<style>
.audit { border-collapse: collapse; width: 100%; max-width: 520px; font: 13px system-ui, sans-serif; color: #241430; background: #FAF7F2; }
.audit__caption { text-align: left; font-weight: 600; padding-bottom: 8px; }
.audit th, .audit td { padding: 10px 12px; text-align: left; border-bottom: 1px solid #24143020; }
.audit thead th { background: var(--accent); color: #FAF7F2; font-weight: 600; }
.audit tbody th[scope="row"] { font-weight: 600; display: flex; flex-direction: column; gap: 2px; }
.audit--striped tbody tr:nth-child(even) { background: #24143010; }
.audit__id { font-size: 11px; color: #24143099; }
.audit__id--mono { font-family: "SFMono-Regular", Consolas, monospace; }
td.audit__id--mono { font-family: "SFMono-Regular", Consolas, monospace; color: #241430; font-size: 12.5px; }
.audit tbody[data-rows="3"] tr:nth-child(n+4) { display: none; }
.audit tbody[data-rows="4"] tr:nth-child(n+5) { display: none; }
.audit tbody[data-rows="5"] tr:nth-child(n+6) { display: none; }
</style>

tailwind

<table class="border-collapse w-full max-w-[520px] font-sans text-[13px] text-[#241430] bg-[#FAF7F2]">
  <caption class="text-left font-semibold pb-2">Security audit trail</caption>
  <thead>
    <tr style="background:#241430" class="text-[#FAF7F2]">
      <th scope="col" class="text-left font-semibold p-2.5 px-3">Actor</th>
      <th scope="col" class="text-left font-semibold p-2.5 px-3">Action</th>
      <th scope="col" class="text-left font-semibold p-2.5 px-3">Target</th>
      <th scope="col" class="text-left font-semibold p-2.5 px-3">Timestamp</th>
    </tr>
  </thead>
  <tbody data-rows="4" class="audit-tw audit-tw--striped">
    <tr class="border-b border-[#24143020]">
      <th scope="row" class="text-left font-semibold p-2.5 px-3">A. Whitfield<span class="block text-[11px] font-normal text-[#24143099] font-mono">usr_8841</span></th>
      <td class="p-2.5 px-3">role.updated</td>
      <td class="p-2.5 px-3 font-mono text-[12.5px]">acct_2210</td>
      <td class="p-2.5 px-3"><time datetime="2026-08-18T08:12:00Z">18 Aug, 08:12</time></td>
    </tr>
    <tr class="border-b border-[#24143020]">
      <th scope="row" class="text-left font-semibold p-2.5 px-3">M. Duarte<span class="block text-[11px] font-normal text-[#24143099] font-mono">usr_1190</span></th>
      <td class="p-2.5 px-3">login.failed</td>
      <td class="p-2.5 px-3 font-mono text-[12.5px]">usr_1190</td>
      <td class="p-2.5 px-3"><time datetime="2026-08-18T07:58:00Z">18 Aug, 07:58</time></td>
    </tr>
    <tr class="border-b border-[#24143020]">
      <th scope="row" class="text-left font-semibold p-2.5 px-3">S. Novak<span class="block text-[11px] font-normal text-[#24143099] font-mono">usr_4402</span></th>
      <td class="p-2.5 px-3">record.deleted</td>
      <td class="p-2.5 px-3 font-mono text-[12.5px]">rec_7734</td>
      <td class="p-2.5 px-3"><time datetime="2026-08-17T22:41:00Z">17 Aug, 22:41</time></td>
    </tr>
    <tr class="border-b border-[#24143020]">
      <th scope="row" class="text-left font-semibold p-2.5 px-3">A. Whitfield<span class="block text-[11px] font-normal text-[#24143099] font-mono">usr_8841</span></th>
      <td class="p-2.5 px-3">permission.granted</td>
      <td class="p-2.5 px-3 font-mono text-[12.5px]">team_09</td>
      <td class="p-2.5 px-3"><time datetime="2026-08-17T19:05:00Z">17 Aug, 19:05</time></td>
    </tr>
    <tr class="border-b border-[#24143020]">
      <th scope="row" class="text-left font-semibold p-2.5 px-3">J. Kocher<span class="block text-[11px] font-normal text-[#24143099] font-mono">usr_2255</span></th>
      <td class="p-2.5 px-3">export.completed</td>
      <td class="p-2.5 px-3 font-mono text-[12.5px]">rpt_5561</td>
      <td class="p-2.5 px-3"><time datetime="2026-08-17T14:30:00Z">17 Aug, 14:30</time></td>
    </tr>
  </tbody>
</table>
<style>
.audit-tw--striped tr:nth-child(even) { background: #24143010; }
tbody[data-rows="3"] tr:nth-child(n+4) { display: none; }
tbody[data-rows="4"] tr:nth-child(n+5) { display: none; }
tbody[data-rows="5"] tr:nth-child(n+6) { display: none; }
</style>

react

export function AuditLog({
  caption = "Security audit trail",
  rows = "4",
  accent = "#241430",
  monospaceIds = true,
  striped = true,
}) {
  const data = [
    { actor: "A. Whitfield", actorId: "usr_8841", action: "role.updated", target: "acct_2210", time: "2026-08-18T08:12:00Z", label: "18 Aug, 08:12" },
    { actor: "M. Duarte", actorId: "usr_1190", action: "login.failed", target: "usr_1190", time: "2026-08-18T07:58:00Z", label: "18 Aug, 07:58" },
    { actor: "S. Novak", actorId: "usr_4402", action: "record.deleted", target: "rec_7734", time: "2026-08-17T22:41:00Z", label: "17 Aug, 22:41" },
    { actor: "A. Whitfield", actorId: "usr_8841", action: "permission.granted", target: "team_09", time: "2026-08-17T19:05:00Z", label: "17 Aug, 19:05" },
    { actor: "J. Kocher", actorId: "usr_2255", action: "export.completed", target: "rpt_5561", time: "2026-08-17T14:30:00Z", label: "17 Aug, 14:30" },
  ].slice(0, Number(rows));
  const mono = monospaceIds ? { fontFamily: "SFMono-Regular, Consolas, monospace" } : {};
  return (
    <table style={{ borderCollapse: "collapse", width: "100%", maxWidth: 520, fontFamily: "system-ui, sans-serif", fontSize: 13, color: "#241430", background: "#FAF7F2" }}>
      <caption style={{ textAlign: "left", fontWeight: 600, paddingBottom: 8 }}>{caption}</caption>
      <thead>
        <tr style={{ background: accent, color: "#FAF7F2" }}>
          {["Actor", "Action", "Target", "Timestamp"].map((h) => (
            <th key={h} scope="col" style={{ textAlign: "left", fontWeight: 600, padding: "10px 12px" }}>{h}</th>
          ))}
        </tr>
      </thead>
      <tbody>
        {data.map((row, i) => (
          <tr key={row.time} style={{ background: striped && i % 2 === 1 ? "#24143010" : "transparent", borderBottom: "1px solid #24143020" }}>
            <th scope="row" style={{ textAlign: "left", fontWeight: 600, padding: "10px 12px" }}>
              {row.actor}
              <span style={{ display: "block", fontSize: 11, fontWeight: 400, color: "#24143099", ...mono }}>{row.actorId}</span>
            </th>
            <td style={{ padding: "10px 12px" }}>{row.action}</td>
            <td style={{ padding: "10px 12px", fontSize: monospaceIds ? 12.5 : 13, ...mono }}>{row.target}</td>
            <td style={{ padding: "10px 12px" }}><time dateTime={row.time}>{row.label}</time></td>
          </tr>
        ))}
      </tbody>
    </table>
  );
}