Pending value
Holds one slot and names whose value is coming, so an absence is never mistaken for a reading.
Overview
Where a number will go, nothing generic may sit. A grey bar promises a value the system may not be able to deliver; a blank reads as “there is no value”. A pending value says which value is coming and, where there is one, what was there before.
It is what Skeleton's rule points at, and it installs with it.
Showing the previous value instead of a spinner
Outside clinical software the modern default is to keep the last-known data on screen while fresh data is fetched, rather than replacing it with a placeholder. It is usually the better pattern: a spinner where a number used to be destroys context, and the reader has to hold the old value in their head.
Here it cuts both ways, and the deciding question is what the reader is about to do.
| Situation | Show | Why |
|---|---|---|
| Re-fetching a value already on screen | The existing value, with its age stated, and a quiet refresh indicator | Replacing a number with a spinner removes information the reader had. The age is what makes it honest. |
| A value the reader is about to act on | The value, its age, and an explicit statement that a newer one is being fetched | A stale value read as current is the same class of error as a wrong-patient value. Age alone is not enough when a decision is imminent. |
| Switching patient, or any change of subject | Nothing from the previous subject, ever. Clear first, then load. | The most dangerous thing this pattern can do. A previous patient's troponin under a new patient's header is a wrong-patient error the interface manufactured itself — see Patient header. |
| After a failed refresh | The old value, its age, and that the refresh failed | Reverting to a blank discards data the reader had. Silently keeping it as though current is worse. |
Age is stated as a time, not a mood. "As of 14:26:38" is checkable; "recently" is not. Where the value has a clinically meaningful staleness threshold, the interface says when it is crossed rather than leaving the reader to compute it.
What the component enforces, and what it only asks for
The smallest component here, and the split is two rows long.
| Rule | Held by | How |
|---|---|---|
| A pending slot always says what is pending | The component | label is required. A placeholder that does not name its value is a blank with extra steps.Asserted: PendingValue: a held value slot is words, not a shape |
| It is announced as busy | The component | aria-busy, politely, so an arriving value does not interrupt a sentence.Asserted: PendingValue: the slot reports itself as busy |
| The slot is cleared on a patient switch | You | The component has no idea a patient exists. Rendering the previous patient's slot under a new header is a wrong-patient event the interface manufactured. |
| A held value carries its age | You | startedAt is a string you pass, and it is optional. |
A rule stated on a component page reads as a rule the component keeps. 2 of these 4 are; 2 are obligations this page was quietly handing to the reader. The one rule with a wrong-patient consequence is on your side.
Do's and don'ts
The number the reader had is still there, with its age. A spinner in this slot would have taken away information and given none back.
The value was on screen a second ago and now it is not. The reader holds it in their head instead, which is where transcription errors come from.
Switching patient
Cleared first, then loaded, and the slot names whose value is coming. Nothing from the previous patient survives the switch.
Switching patient
The previous patient's result under the new patient's header. The interface has manufactured a wrong-patient error out of a loading optimisation.
Peak troponin — loading, started 15:10
The slot names whose value is coming and how long it has been coming. A reader can tell an awaited result from an absent one.
Peak troponin —
A grey bar where the number goes. If the assay never resolves, this sits here indefinitely or vanishes into an empty cell, and both read as “there is no value”.
Accessibility
- It announces what is pending, in words — “Peak troponin, loading” — because the visual placeholder carries nothing.
- The region is
aria-busywhile it waits, and the announcement is polite: a value arriving must not interrupt a sentence. - A held value keeps its age in text, not in a colour or an opacity that a low-contrast display will lose.
- The slot is cleared on a patient switch before anything loads into it.
Outcomes of use
- Effectiveness — a value that has not arrived is distinguishable from one that does not exist. Those are different facts about the patient.
- Efficiency — the reader keeps the number they had, with its age, instead of holding it in their head.
- Satisfaction — not being shown a placeholder where a result belongs. Attributes believed to contribute to an outcome; the outcome is settled by observing real use, not by this page — see Usability & context of use.
Clinical safety notes
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.
- A held value carries its age. (you) Mitigates: a stale number read as current.
- The slot is cleared on a patient switch before loading. (you) Mitigates: the previous patient's result under the new patient's header — a wrong-patient event manufactured by the interface.
- A pending slot is never blank. (the component) Mitigates: an awaited result read as an absent one — see what an empty field means.
Implementation
$ npx shadcn@latest add https://md.notjustany.tech/r/pending-value.json
<PendingValue label="Peak troponin" startedAt="15:10" />
// label is required: a placeholder that does not say what is coming is
// a blank with extra steps.