Components · Feedback & status

Event log

The durable record. Append-only by the shape of its props: there is no edit, no delete and no clear.

Stable · v1.0 shadcn/ui WCAG 2.2 AA

Overview

Three pages in this system already argue from a durable record. Toast queue says a toast is safe to dismiss because what it reports is written somewhere permanent. Alert banner says a critical alert always leaves a trace. Acknowledge & escalate says an acknowledgement is terminal because it persists. Until this component existed, all three arguments were complete and had nothing underneath them.

The rule

A record is what happened, not what is currently believed. An entry is never edited and never removed. An entry that turns out to be wrong is corrected by a later entry that says so, and both stand.

Append-only

There is no onEdit, no onDelete and no onClear. A log that can be tidied is not expressible.

Attributed

Every entry names who, and whether that who was a person or software. Those are different facts about the same action.

Honest about what it shows

The count of what is shown against what exists is required, so a shortened view cannot read as the whole record.

Anatomy

Event log · one alert, acknowledged and later corrected

Alert activity · HARLAND, A. · MRN 44 812 907

3 of 47 · newest first

  1. 14:41:07 CEST   Corrected the acknowledgement   STEMI alert · 14:26

    S. Whitfield · Registrar

    Acknowledged in error while the patient list was open; the alert remains active.

  2. 14:32:07 CEST   Acknowledged the alert   STEMI alert · 14:26

    S. Whitfield · Registrar

  3. 14:26:38 CEST   Raised a critical alarm   STEMI pattern — anterior leads V2–V4

    AcuteLine 4.2 · automatic

    Superseded by a later entry (evt-118). This entry stands as recorded.

Showing 3 of 47. The rest of the record is not on this screen.

ElementRule
Time Absolute, with its zone, in a real <time> element. Never relative: “3 hours ago” is wrong the moment a tab is left open, and a log is read long after it is written.
Action What happened, in clinical terms. “Acknowledged the STEMI alert”, not “UPDATE alerts SET ack=1”.
Subject What it happened to. An entry that does not name its subject is not auditable.
Actor A person with a role, or software with a version. Marked in words, because this system has no icons and because a reader must be able to tell an action somebody took from one that happened to them.
Correction notice Rendered on the superseded entry, which stays. Never struck through and never hidden — a log that removes what turned out to be wrong is a log nobody can audit.
Shown of total Required. A shortened view that does not say so reads as the whole record.

What a log may never do

When the actor is not a person

Most entries in a clinical event log are written by software, and a reader scanning for what a colleague did should not have to work out which is which. The actor union makes the distinction structural rather than a naming convention.

Do's and don'ts

Do

14:41 Corrected the acknowledgement · acknowledged in error

14:32 Acknowledged the alert

Both entries stand. A reader can see that the alert was dismissed by somebody who was not looking at it, which is the fact worth having.

Don't

14:32 Acknowledged the alert — removed

The mistaken acknowledgement is gone, and with it the only evidence that the alert was ever dismissed without being read.

Do

Raised a critical alarm · AcuteLine 4.2 · automatic

The reader can tell software raised it, and which version. A later model update makes that version the thing they need.

Don't

Raised a critical alarm · System

“System” is not an actor. Nothing in the record says which software, at which version, on which rule.

Do

12 alarms · 14:22, 14:22, 14:23, 14:23, 14:24 …

Twelve entries, twelve times. The rate is visible, and the rate is the finding.

Don't

Alarm raised ×12

One entry with a multiplier. An alarm system firing twelve times in four minutes is now indistinguishable from one that fired sensibly.

What the component enforces, and what it only asks for

A displayed log is a rendering. The rules that make a record trustworthy are almost all about storage, and none of them can be held by something that draws a list.

RuleHeld by How
Entries cannot be edited, removed or clearedThe component There is no onEdit, onDelete or onClear in the props. A log that can be tidied is not expressible.
Asserted: EventLog: no entry can be edited, removed or cleared
Every entry names an actorThe component actor is required and is a union, so an unattributed entry and an ambiguous one are both unwritable.
Asserted: EventLog: every entry names an actor, and says whether it was software
A superseded entry stays and says soThe component supersededBy renders a notice on the entry rather than hiding or striking it.
Asserted: EventLog: a superseded entry stays, and says it was superseded
A shortened view says soThe component totalCount is required and is rendered against the number shown.
Asserted: EventLog: a shortened view says how much of the record it is showing
The order is statedThe component orderedBy is required, and the list is an <ol> because the order is the meaning.
Asserted: EventLog: the order is stated and the list is ordered markup
A correction is named in the reader’s termsThe component By the correcting entry’s time and action, or as not shown here. It printed the entry’s id — “(evt-118)” — which no reader can use.
Asserted: EventLog: a superseded entry stays, and says it was superseded
The record itself is append-onlyYou This draws a list. Whether your storage permits an UPDATE on a recorded event is the question that actually decides whether any of this is true, and it is entirely outside the browser.
The record is completeYou totalCount is a number you pass. If your query dropped entries before the component saw them, it will state a total with complete confidence.
Times are correct and in one zoneYou Preformatted strings. A log mixing zones reads as a sequence that did not happen — see Date & time picker.
Entries are ordered by time and not re-sortedYou orderedBy is a string describing an array you built. Nothing here can check the words are true.
The record is tamper-evidentYou Nothing here is signed or hashed. A rendering cannot make a record trustworthy; it can only avoid misrepresenting one.
Why this is written down

A rule stated on a component page reads as a rule the component keeps. 5 of these 10 are; 5 are obligations this page is handing to the reader. Every rule that makes a record trustworthy rather than merely well-drawn is on your side of the table, and that is not a gap this component could ever close.

Accessibility

Outcomes of use

Clinical safety notes

Risk controls this page specifies

Trace these in your risk file (ISO 14971) and usability engineering file (IEC 62366-1). Which of these the component keeps and which are yours is stated in the guarantees table; a control the component does not keep is one your risk file must show you keep.

Implementation

$ npx shadcn@latest add https://md.notjustany.tech/r/event-log.json
<EventLog
  caption="Alert activity · HARLAND, A."
  orderedBy="newest first"   // required: an unstated order is a claim about causality
  totalCount={47}                // required: a shortened view cannot read as the whole record
  entries={[
    { id: "evt-118", at: "14:41:07 CEST",
      actor: { kind: "person", name: "S. Whitfield", role: "Registrar" },
      action: "Corrected the acknowledgement", subject: "STEMI alert · 14:26" },
    { id: "evt-092", at: "14:26:38 CEST",
      actor: { kind: "system", name: "AcuteLine", version: "4.2" },
      action: "Raised a critical alarm", subject: "STEMI pattern",
      supersededBy: "evt-118" },
  ]}
/>

// There is no onEdit, no onDelete and no onClear. Correcting a record
// means appending an entry that says so; both stand.
NotJustAnyMed.Tech Design System · Progress & activity · v1.0 · draft for review
Reference applications named in this system are fictional; all patient data shown is fabricated.