List
A flat set that states its order, its size and what a bulk action would act on.
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
-
12-lead ECGST elevation V2–V4 · analysed, model v4.2
-
hs-cTnI · repeat47 ng/L · ref < 34 ng/L · central lab
-
12-lead ECGNo acute change · analysed, model v4.2
-
hs-cTnI · baseline14 ng/L · ref < 34 ng/L · central lab
| Part | Rule |
|---|---|
| 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
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.
- Never sort by relevance, confidence or model score without saying so and offering the underlying deterministic order. See Confidence & uncertainty.
- Never truncate silently. "Showing 10 of 34" with a control to see the rest, or show all 34. A list that stops at ten with no indication has hidden twenty-four things.
- Never reorder under the reader. New items arriving while the list is on screen are appended and marked, not slotted in — the same rule as Data grid.
- Empty is not blank. An empty list states which of "none exist", "none match the filter" and "could not load" applies — see Empty state.
- Filtered lists carry their filters visibly as removable tags — see Filter.
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?
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.
- The selected count is always visible, whether or not any selected item is: "3 selected · 1 shown". The gap between those two numbers is the whole hazard, so it is rendered rather than left to be discovered.
- The selected set is reachable in one action — a control that shows just the selected items. A count nobody can expand is a number the clinician has to trust.
- Any action names what it will act on, in the confirmation, by count and by scope: "Export 3 selected patients, 2 of which are not currently shown." The confirmation is where the drift gets caught, and it is the last chance.
- Changing the filter never silently drops a selection. If the component does clear hidden selections, it says so as it happens; if it keeps them, it says that too.
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 action | Permitted |
|---|---|
| Export, print, copy identifiers to a worklist | Yes. The action does not record a judgement about any of them. |
| Assign to a colleague, add to a queue | Yes, with the set named in the confirmation. It moves work; it does not close it. |
| Acknowledge, dismiss, mark reviewed, sign, accept | No. 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 items | No. 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
- A locked item says why, in the row. The usual pattern puts the reason in a tooltip on hover; that reason does not exist on a touch cart, and an option that cannot be chosen for an unstated reason reads as a fault.
- Locked is not hidden. An item the clinician may not select is still an item they need to know exists — removing it changes the set they believe they are looking at.
- Select-all skips locked items and says how many it skipped. Silently selecting fewer than "all" is the same class of error as the filtered count above.
Order, and rearranging by hand
- Sorting a list with a selection preserves the selection and states it. Items moving is expected; the set the clinician assembled is not something a re-sort edits.
- Manual reordering is available only where order is the clinician's to set — an order set they are composing, a print sequence. Never in a list whose order is a clinical statement, per Order and completeness.
- Where reordering exists, it is not drag-only. Move-up and move-down controls on each row, per SC 2.5.7 — and they work on a cart, where dragging a row while the trolley moves is how items land in the wrong place.
States
| State | Rendering |
|---|---|
| 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.
| Rule | Held by | How |
|---|---|---|
| A selection header states both counts | The 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 covers | The 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 stated | The 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 order | You | 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 set | You | 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 cleared | You | The component holds no selection state. |
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.
Numerator, denominator, filter state and order. Four facts that stop the list from making a claim it cannot support.
Fifteen recordings are hidden by a filter the clinician cannot see, in an order they cannot check.
- hs-cTnI · repeat47 ng/L · ref < 34 ng/L · central lab
The secondary line makes the item actionable without opening it. Value, unit, reference, source, absolute time.
- TNI2 result
An internal code, no value, and a relative time that is wrong the moment the tab is left open.
- 12-lead ECGanalysis unavailable · waveform viewable
A degraded item stays in the set with its state named. The count still adds up.
- hs-cTnI · baseline
The ECG whose analysis failed has been dropped from the list entirely. Nothing on screen says a recording exists.
4 of 19 · filtered
Two different actions, two labels. The clinician chooses which one they meant instead of discovering it afterwards.
4 of 19 · filtered
Four, or nineteen? Both readings are reasonable, the implementation picked one silently, and the difference is fifteen patients.
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.
1 item shown
Export selected?
Two selections are still live behind the filter. Three files arrive and the clinician expected one.
- Export selected
- Assign to a colleague
Bulk actions that move work or copy it out. Neither records a judgement about any individual finding.
- Mark 12 selected as reviewed
Records that a person considered twelve specific findings. Eleven of them they never opened. See Acknowledge.
- 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.
- 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
- A real
<ul>/<li>so the set size is announced. A stack of divs tells a screen-reader user nothing about how many items exist. - The order statement and count are inside the list's labelled region, so they are reachable in the same breath as the items rather than orphaned above it.
aria-currentfor the selected item, alongside fill and an inset rule. Three signals, one non-visual.- Trees use
role="tree",treeitemandgroup, witharia-expanded,aria-level,aria-setsizeandaria-posinset. - A nested list is a Tree, with its own keyboard model — one tab stop, arrows that move and expand. A flat list has no such model and needs none: its rows are reached with Tab.
- Branch state is in the accessible name — "Laboratory, 6 items, 1 critical, collapsed" — not only in a coloured chip.
- Rows are not link-in-link. A clickable row containing its own buttons is two overlapping targets; either the row navigates or the buttons act, never both in the same pixel.
- Targets ≥ 24 px including the tree's expand affordance, which is the one most often built at 12 (WCAG 2.2 SC 2.5.8).
- Reflow to 320 px — list items stack their secondary line, and tree indentation caps so deep levels do not push content off-screen (SC 1.4.10).
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.
- Effectiveness — the clinician knows the set is complete, or knows exactly how it is not. Nothing relevant is behind an unmarked collapse.
- Efficiency — the secondary line answers the question most items are opened to answer, so most items do not need opening.
- Satisfaction — an order that can be checked. Trust in a list is almost entirely trust in its ordering.
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.
- Order stated in words. (you) Mitigates: position read as clinical priority.
- Count shown as
n of N. (the component) Mitigates: a filtered subset read as the whole record. - No silent truncation. (the component) Mitigates: relevant items existing beyond an invisible cut-off.
- Collapsed branches report contained state. (you) Mitigates: a critical result concealed by a closed node.
- Degraded items stay in the set with their state named. (you) Mitigates: a recording believed not to exist because its analysis failed.
- No reordering under the reader. (you) Mitigates: opening the wrong item because the row moved between look and click.
- Absolute timestamps. (you) Mitigates: a relative time going stale on an unattended screen.
- Empty states distinguish none-exist from none-match from failed-to-load. (you) Mitigates: a load failure read as an absence of findings.
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>
Related
- Tree — the same set when the hierarchy is the point.
- Data grid — when the items have columns worth comparing.
- Filter — what is hiding the rest of the set.
- Empty state — a list with nothing in it, and why that is not one thing.