Components · Feedback & status

Empty state

Nothing on screen is the most ambiguous thing an interface can show. In clinical software it has at least four causes, three of which are problems — so an empty state's job is to say which.

Stable · v1.0 shadcn/ui WCAG 2.2 AA

Overview

In consumer software an empty state is a chance to be charming. Here it is a diagnostic surface, because "no cases awaiting review" and "the ECG feed died an hour ago" produce identical screens unless the component distinguishes them — and a clinician reading the first when the second is true will stop looking.

The rule underneath everything on this page: an empty state must prove why it is empty. A timestamp and a source count do more for safety than any illustration.

Diagnostic

Names its cause. Genuinely empty, filtered, still loading and failed are four different states and never share a rendering.

Evidenced

A healthy empty state carries proof of life — when the system last checked, and how many sources it is watching.

Plain

No illustrations, no encouragement, no personality. A clinician deciding whether to trust an empty queue needs facts, not reassurance.

The four empty states

CauseSeverityMust say
Genuinely emptyInformational The state, plus proof of life — last check, sources monitored
FilteredAdvisory How many rows exist, what is hiding them, and a one-action reset
Loading Skeleton rows. Never a blank region, never a message claiming emptiness
FailedUrgent That data could not be loaded, which sources are affected, and what to do meanwhile
Failure is never an empty state

If the system could not load the data, the region does not render an empty state at all — it renders an Alert Banner at Urgent. Empty means "we looked and there is nothing". Failed means "we do not know". Collapsing the second into the first is the single most dangerous thing this component can do, because it converts a system fault into apparent clinical good news.

Anatomy

Genuinely empty · with proof of life
No cases awaiting review
The queue is current. New ECGs appear here automatically.
last analysis 14:47:12 · monitoring 4 of 4 sources · updated 8 s ago
ElementRule
Title States the fact, not a feeling. "No cases awaiting review", never "All caught up".
Description What will change this state, in one sentence.
Proof of life Required on any clinical queue. Last successful check, sources healthy versus total, and freshness of the view.
Action Only where one exists — clearing a filter, retrying. Never an invented one.

The other three

Filtered · loading · failed
No cases match the current filter
23 cases in scope, all hidden by filter: my patients only. Critical cases are always shown regardless of filter.
Patient Finding Waiting

Note that only the first is an empty state at all. Filtered renders an Advisory, failed renders an Urgent, and loading renders skeleton rows that reserve the same space the real rows will occupy — see Grid & layout.

Writing it

Do
No cases awaiting review
The queue is current.
last analysis 14:47:12 · monitoring 4 of 4 sources

Empty and demonstrably alive. A clinician can tell the difference between quiet and broken without leaving the screen.

Don't
All caught up!
Nothing to review right now.

Congratulates the clinician on a state that may be a dead ingestion pipeline. Identical rendering whether the ward is quiet or the feed died an hour ago.

Freshness

An empty state is a claim about now, and it decays. Three rules:

Do's and don'ts

Do
No cases awaiting review
The queue is current.
last analysis 14:47:12 · monitoring 4 of 4 sources

Empty and demonstrably alive. Quiet ward and dead pipeline are distinguishable without leaving the screen.

Don't
All caught up
Nothing to review right now.

No timestamp, no source count. Identical whether the ward is quiet or the ECG feed died an hour ago.

Accessibility

Outcomes of use

What this contributes to, in the terms of Usability & context of use. These are attributes believed to contribute to an outcome; the outcome itself is settled by observing real use in a specified context, not by this page.

Clinical safety notes

Risk controls carried by this component

Trace these in your risk file (ISO 14971) and usability engineering file (IEC 62366-1).

Implementation

$ npx shadcn@latest add https://md.notjustany.tech/r/empty-state.json
// The four causes are a discriminated union, so "empty" cannot be
// rendered without the evidence that justifies it.
type RegionState =
  | { kind: "empty";    lastCheck: string; sourcesOk: number; sourcesTotal: number }
  | { kind: "filtered"; total: number; hidden: number; filterLabel: string }
  | { kind: "loading" }
  | { kind: "failed";   affected: string[]; lastSuccess: string }

<EmptyState state={state} onClearFilter={clear} onRetry={retry} />

// failed renders an AlertBanner at urgent, never an empty state.
// loading renders skeleton rows sized to the real rows.
PropTypeNotes
stateRegionState Required. empty cannot be constructed without lastCheck and the source counts.
clinicalboolean Default true. Enforces proof of life; set false only for non-clinical regions such as an empty settings list.
staleAfterISO 8601 duration Beyond this, the empty state escalates to an Advisory.
NotJustAnyMed.Tech Design System · Empty state · v1.0 · draft for review
Reference applications named in this system are fictional; all patient data shown is fabricated.