Components · Data

Data grid

The substrate under every list of patients, results and events. Its defaults decide what a clinician sees first and what they never see at all, which makes sorting, filtering and row insertion safety behaviours rather than conveniences.

Stable · v1.0 shadcn/ui TanStack Table WCAG 2.2 AA

Overview

A general-purpose data grid optimises for flexibility: sort anything, filter anything, hide anything, remember what the user did last time. Every one of those defaults is wrong in a clinical queue, because each of them can silently remove a patient from view.

This component keeps the flexibility and inverts the defaults. Everything is available; almost nothing is on by default; anything currently hiding data says so on screen.

Complete by default

Opens showing every row in scope. No remembered filter, no collapsed group, no pagination hiding the top of a queue.

Stable under the hand

Rows never move beneath a pointer. Live data arrives staged and announced, inserted when the clinician is ready.

Honest about state

Any non-default sort, active filter or hidden column is stated in the grid's own chrome, legible to someone who did not set it.

Anatomy

Data grid · default state
23 cases · sorted by priority, then longest waiting Density: comfortable
Priority indicator Finding
Critical HARLAND, A.
MRN 44 812 907
STEMI pattern — anterior V2–V4 4 min0.94
Urgent OKONKWO, B.
MRN 51 330 264
hs-troponin rising — NSTEMI not excluded 19 min0.71
Urgent DELACROIX, M.
MRN 47 120 883
ST depression — inferior leads 27 min0.66
Advisory NAKAMURA, T.
MRN 58 904 471
Interpretation limited — paced rhythm 33 min
ElementRule
State bar Row count and the active sort, always. This is the component's honesty surface.
Sticky header Column meaning stays visible while scrolling. Never sticky at 200 % zoom, where it would consume the viewport.
Sortable header A real <button> inside the <th>, with aria-sort on the header.
Priority rail 4 px of IEC hue where rows carry clinical priority. Always paired with a text column.
Selection --accent fill plus aria-selected. Never colour alone.

Sorting

The default sort is a product decision with clinical consequence, declared once and enforced by the component. In AcuteLine it is priority, then longest waiting — see Triage worklist.

Non-default sort · stated and reversible
Sorted by confidence, highest first — not clinical priority
Priority indicator
HARLAND, A.0.944 min
VASQUEZ, R.0.8841 min
OKONKWO, B.0.7119 min

A reviewed 41-minute case now sits above an urgent 19-minute one. The bar says so in words, not with a small arrow icon.

Live data

Rows never move under the pointer

New rows are staged, not inserted. A banner announces how many are waiting and the clinician inserts them. Auto-insertion is permitted only after a documented idle interval with no pointer or keyboard activity — because a queue that reorders while someone is reaching for row two produces wrong-patient selection.

Staged arrivals
2 new cases — 1 critical, 1 urgent
Priority indicator Patient Finding Waiting
HARLAND, A.STEMI pattern — anterior V2–V44 min
OKONKWO, B.hs-troponin rising19 min

Once inserted, new rows carry a temporary marker so a clinician can see what changed since they last looked. The marker is positional and textual, never a colour wash that could be mistaken for priority.

Filtering and columns

Density

DensityRow heightUseTouch
comfortable~44 px Default. Any grid whose rows are tappable.Yes
default~36 px Workstation review with pointer input.No
compact~28 px Dense analytic review, pointer only, non-clinical-priority data.No

Density never removes information — it reduces padding only. A compact grid that drops the MRN is not compact, it is incomplete. On touch platforms the grid is locked to comfortable and the row must satisfy the physical touch floor; see Scaling.

Empty, loading and degraded

Do
No cases awaiting review
Queue is current. Last analysis 14:47. Monitoring 4 sources.

Empty and demonstrably alive. The timestamp and source count are the proof.

Don't
Nothing here

Indistinguishable from a dead ingestion pipeline. An empty clinical queue must always prove why it is empty.

Do's and don'ts

Do
2 new cases — 1 critical, 1 urgent

New rows staged and announced. The clinician inserts them when their hand is not already moving.

Don't
NEW — inserted at top just now
OKONKWO, B.

Live insertion at the top. Everything below moves down mid-reach, and the wrong patient opens.

Do
23 cases · sorted by priority, then longest waiting Density: comfortable

The state bar states the sort in words, permanently, for whoever walks up to the screen.

Don't
23 cases

A small arrow in a header. A colleague cannot tell this queue is sorted by confidence, not acuity.

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/data-grid.json
// TanStack Table under a shadcn-styled shell. The clinical defaults are
// baked into the component, not left to each call site.
<DataGrid
  columns={columns}
  data={cases}
  // declared once; restored on every session start
  defaultSort={[{ id: "priority", desc: true },
               { id: "waiting",  desc: true }]}
  persistState={false}          // governed: never true in a clinical queue
  stageIncoming                     // new rows announced, inserted on request
  autoInsertAfterIdle="PT30S"
  bypassFilter={(row) => row.priority === "critical"}
  density="comfortable"
  onRowActivate={(row) => openEvidence(row.id)}
/>
PropTypeDefaultNotes
defaultSortSortingState Required. Restored on every session start.
persistStatebooleanfalse Setting true on a clinical queue fails lint.
stageIncomingbooleantrue Staged arrivals. Disable only for non-clinical grids.
bypassFilter(row) => boolean Rows that render regardless of active filters.
densitycomfortable | default | compact comfortableLocked to comfortable on touch.
onRowActivate(row) => void Must open evidence, never an irreversible action.
NotJustAnyMed.Tech Design System · Data grid · v1.0 · draft for review
Reference applications named in this system are fictional; all patient data shown is fabricated.