Components · Data

List

A flat set that states its order, its size and what a bulk action would act on.

Stable · v1.0 shadcn/ui WCAG 2.2 AA Merged: List · Tree

Overview

A list is read as a claim whether or not one was intended: position reads as priority, and a count with no denominator reads as the whole set. Most of this page is about closing the gap between what a list shows and what a clinician concludes from it.

Depth is a different component. Tree was documented here and shipped under this install command; a product with a flat worklist has no use for one.

Anatomy

List with stated order and provenance
Recordings this encounter 4 of 4 · newest first
  • 12-lead ECG
    ST elevation V2–V4 · analysed, model v4.2
    15:41:02
  • hs-cTnI · repeat
    47 ng/L · ref < 34 ng/L · central lab
    15:41:00
  • 12-lead ECG
    No acute change · analysed, model v4.2
    14:26:38
  • hs-cTnI · baseline
    14 ng/L · ref < 34 ng/L · central lab
    14:41:00
PartRule
Order statement Required. "Newest first", "by priority then time". Present even when the order looks obvious.
Count 4 of 4, or 4 of 19 · filtered. The denominator is the unfiltered total, always.
Primary line What the item is. Full clinical name, never an internal code.
Secondary line Enough to act without opening the item — the value with its unit, the finding, the source. Optional but usually the reason the list is useful.
Timestamp Mono, tabular, absolute. Relative times ("2 h ago") never appear alone — see International design.
Current item aria-current plus fill and an inset rule. Never fill alone.

Order and completeness

The rule that carries the risk

A clinician scanning a list reads position as priority whether you intended it or not. So an order that is not stated is an implied clinical claim you did not mean to make. Every list in this system states its order in words and states the size of the set it is drawn from. A list showing 4 items out of 19 that says only "4 items" is misinformation, not brevity.

Selecting from a list

A list whose items can be chosen is a different component from a list that is read, and it carries a failure the reading kind does not: the selection and the visible set can drift apart. Everything below follows from that.

Select all, of what?

The ambiguity

A list showing 4 of 19 · filtered with a select-all control offers two entirely different actions under one label. Does it select the four on screen, or the nineteen the filter is hiding fifteen of? Both are reasonable readings, most implementations pick one silently, and the difference is fifteen patients.

The control says which. "Select all 4 shown" or "Select all 19", and where both are useful, both are offered as separate controls. A bare "Select all" beside a filtered list is not a label, it is a coin toss.

Selection outliving what is visible

Three items are selected. The clinician narrows the filter and two of them drop out of view. Are they still selected? In most implementations yes, invisibly — so "export selected" then produces three files when one is on screen.

What selection may never be used for

Acknowledge & escalate forbids bulk acknowledgement in any form — not as a toolbar action, not behind a setting. Multi-select is the most natural way to build one, so the boundary is stated here too.

Bulk actionPermitted
Export, print, copy identifiers to a worklistYes. The action does not record a judgement about any of them.
Assign to a colleague, add to a queueYes, with the set named in the confirmation. It moves work; it does not close it.
Acknowledge, dismiss, mark reviewed, sign, acceptNo. Each of those records that a person considered a specific finding. Doing it to a set records something that did not happen.
Delete or discard clinical itemsNo. The one-by-one cost is the point.

The test is whether the action asserts something about each item individually. If it does, the clinician performs it individually — see Editing the draft, where the same argument settles what a single acceptance can honestly cover.

Locked and unavailable items

Order, and rearranging by hand

States

StateRendering
Loading Skeleton rows at the known count where the count is known; otherwise an activity indicator with the region named. Never an empty list that later fills.
Partial The items that loaded, plus an explicit row stating what did not and why. Never silently short.
Filtered Count reads n of N · filtered, with the filter tags above the list.
Empty The distinguishing sentence — none exist, none match, could not load.
Stale Last-updated time visible; the list never presents old data as current. See Interaction states.
Item unavailable The item still renders, with its state named. It does not disappear from the set — a row that vanishes changes the denominator without telling anyone.

What the component enforces, and what it only asks for

The header holds the counting rules. The list holds almost nothing else, because what a list is showing and in what order is entirely what you passed it.

RuleHeld by How
A selection header states both countsThe component shownCount and totalCount are required, so “4 of 19” cannot become a bare “4”.
Asserted: SelectionHeader: the gap between selected and shown is rendered
Select-all names the set it coversThe component Separate labelled actions for the shown set and the whole set; a bare “Select all” is not offered.
Asserted: SelectionHeader: select-all names the set it acts on
A selection hidden behind a filter is statedThe component selectedShown against selectedCount renders the gap.
Asserted: SelectionHeader: no drift means no second number and no escape hatch
The stated order is the real orderYou The order is the order of the array. Nothing here can check that the words describing it are true, and position reads as priority whether or not you meant it.
A degraded item stays in the setYou An item dropped before it reaches the component is invisible to it, and the count still adds up.
Selection survives a re-sort, or is clearedYou The component holds no selection state.
Why this is written down

A rule stated on a component page reads as a rule the component keeps. 3 of these 6 are; 3 are obligations this page was quietly handing to the reader. The component can stop a count lying about its denominator. It cannot stop the list itself being the wrong list.

Do's and don'ts

The pair about a collapsed branch declaring its contents moved to Tree.

Do
Recordings 4 of 19 · filtered · newest first

Numerator, denominator, filter state and order. Four facts that stop the list from making a claim it cannot support.

Don't
Recordings 4 items

Fifteen recordings are hidden by a filter the clinician cannot see, in an order they cannot check.

Do
  • hs-cTnI · repeat
    47 ng/L · ref < 34 ng/L · central lab
    15:41:00

The secondary line makes the item actionable without opening it. Value, unit, reference, source, absolute time.

Don't
  • TNI2 result
    2 h ago

An internal code, no value, and a relative time that is wrong the moment the tab is left open.

Do
  • 12-lead ECG
    analysis unavailable · waveform viewable
    15:41:02

A degraded item stays in the set with its state named. The count still adds up.

Don't
  • hs-cTnI · baseline
    14:41:00

The ECG whose analysis failed has been dropped from the list entirely. Nothing on screen says a recording exists.

Do

4 of 19 · filtered

Two different actions, two labels. The clinician chooses which one they meant instead of discovering it afterwards.

Don't

4 of 19 · filtered

Four, or nineteen? Both readings are reasonable, the implementation picked one silently, and the difference is fifteen patients.

Do

3 selected · 1 shown Show selected

Export 3 selected patients, 2 of which are not currently shown.

The gap between selected and visible is the hazard, so it is rendered. The confirmation is the last chance to catch it.

Don't

1 item shown

Export selected?

Two selections are still live behind the filter. Three files arrive and the clinician expected one.

Do
  • Export selected
  • Assign to a colleague

Bulk actions that move work or copy it out. Neither records a judgement about any individual finding.

Don't
  • Mark 12 selected as reviewed

Records that a person considered twelve specific findings. Eleven of them they never opened. See Acknowledge.

Do
  • Contrast CT — abdomen Not selectable · eGFR below protocol threshold

The reason is in the row. A clinician can act on it — check the eGFR — rather than assume the interface is broken.

Don't
  • Contrast CT — abdomen

Greyed, with the reason in a hover tooltip that does not exist on a cart. An option that cannot be chosen for an unstated reason reads as a fault.

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 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/list.json
<SelectionHeader
  selectedCount={2} selectedShown={1}
  shownCount={4} totalCount={19}   // both required: "4 of 19", never a bare 4
  onSelectShown={selectShown} onSelectAll={selectAll}
/>
<List label="Recordings this encounter">
  <ListItem primary="12-lead ECG" secondary="ST elevation V2–V4"
    meta="15:41:02" />
</List>
NotJustAnyMed.Tech Design System · List & tree · v1.0 · draft for review
Reference applications named in this system are fictional; all patient data and reference ranges shown are fabricated and illustrative.