Clinical validation, made legible.
The single reference for building Probatio screens, for people and coding agents alike. When this page and a screen disagree, this page wins; when it is silent, prefer the option that makes a wrong release harder.
1 · Principles
- 01
Safety over speed
Releasing a result is the most consequential action. It is never the default, never a single accidental click, and always signed. - 02
Never color alone
Every status carries a text flag (L, H, LL, HH, HELD, STALE). Color reinforces meaning, it never carries it. - 03
A number never travels alone
A result always shows its unit, reference range and analyzer. Without them it is not displayed. - 04
Absence is explicit
Stale, missing or pending data is drawn with the hatched stale pattern and an age. Nothing silently falls back to the last known value. - 05
Every block names its exit
A disabled action states why, and the screen offers the path that unblocks it (document the call, record corrective action). - 06
Dense, calm, traceable
High information density on a quiet neutral ground. Rule versions, operators and timestamps are visible where the decision is made.
2 · Color
Warm paper neutrals hold the interface; one deep teal carries action and selection. Saturated colors are reserved for clinical meaning (section 3) and never used for decoration.
Neutrals & shell
- bg.ground
--pb-bg-ground - bg.surface
--pb-bg-surface - bg.subtle
--pb-bg-subtle - line.default
--pb-line - line.strong
--pb-line-strong - text.primary
--pb-text - text.secondary
--pb-text-2 - text.muted
--pb-text-muted - shell.bg
--pb-shell
Action & focus
- action.primary
--pb-action - action.hover
--pb-action-hover - selection.bg
--pb-selection - focus.ring
--pb-focus - demo.marker
--pb-demo
Clinical status
- CRITICAL
- ABNORMAL
- WARNING
- PASSED
- HELD
- AMENDED
- STALE
- INFORMATION
Values read live from the stylesheet.
3 · Clinical status semantics
One meaning per color, across every screen. Critical is the only solid fill, so it stays the loudest element whatever surrounds it. Each pair passes 4.5:1.
| Token | Sample | Meaning | Use it for | Never for |
|---|---|---|---|---|
| status.critical | HH CRITICAL | Life-threatening value, QC rejection | Critical values, rejected runs, overdue STAT | Errors in forms, generic alerts |
| status.abnormal | HL | Outside reference range | Result flags H / L, non-conformities | Warnings about the system |
| status.warning | 1-2sΔ +48 % | Needs a human look, not blocking | QC warning, delta check, acknowledgements | Out-of-range results |
| status.ok | QC OK✓ MATCHED | Check passed | Passed rules, identity matches, released | Normal results (left unflagged) |
| status.held | QC HELD | Blocked by the system | Results held by QC, locked steps | User-initiated pauses |
| status.amended | AMENDED v2 | Released then corrected | Amended reports and their history | Drafts, edits before release |
| status.stale | NO DATA 14 MIN | Missing or out-of-date data | Silent analyzer, delayed feed, pending values | Disabled controls |
| status.neutral | STATDERIVED | Information, no judgement | Priority, provenance, counts | Anything that needs attention |
4 · Typography
IBM Plex Sans Condensed for interface text, JetBrains Mono with tabular figures for every value, code, identifier and timestamp. Both are self-hosted (OFL) and listed in docs/DATA_SOURCES.md.
- Decimal places come from the analyte configuration, never from the raw float (K+ 1 decimal, Na+ 0, creatinine 0).
- Use the true minus sign (−) and thin separators; never truncate a value or a unit with an ellipsis.
- Dates DD/MM/YYYY, times 24 h HH:mm, seconds only in audit and rule traces.
5 · Spacing, density, radius
Spacing scale · base 4 px
- space.1
- space.2
- space.3
- space.4
- space.5
- space.6
- space.8
- space.12
Heights & radius
- Table row · default
- Table row · tracking (stepper)
- Chip
- Control (input, secondary button)
- Consequential action (release, call)
- Shell header
- Radius · chip / control / card / dialog
- / / /
Release, critical-call and reject buttons are always 44 px tall and full width in their panel, so they cannot be confused with routine actions.
6 · Components
Buttons
Primary = the expected next step (one per panel). Danger = a protocol to start, never a destructive shortcut. A disabled button always carries its reason in the label or right under it.
Result row · anatomy
| Analyte | Result | Unit | Flag | Reference | Position in the reference interval | Previous | Delta | Analyzer · QC | Rules |
|---|---|---|---|---|---|---|---|---|---|
| Electrolytes & renal | |||||||||
| 138 | mmol/L | 136 – 145 | 140 | −1.4 % | CHEM-01QC OK | AV v3.2 ✓ | |||
| 6.8 | mmol/L | HH CRITICAL | 3.5 – 5.1 | 4.6 | ▲ +2.2 · +48 % | CHEM-011-2s | AV BLOCKED | ||
| 18 | mmol/L | L | 22 – 29 | 21 | −14 % | CHEM-01QC OK | REVIEW | ||
Without unit, range or analyzer the row refuses to render:
| Analyte | Result | Unit | Flag | Reference | Position in the reference interval | Previous | Delta | Analyzer · QC | Rules |
|---|---|---|---|---|---|---|---|---|---|
| Potassium: result not displayed, unit missing. A number never travels alone. | |||||||||
All eight parts are mandatory. Range bar: the middle 50 % is the reference interval, the marker clamps to the ends when the value falls outside the scale.
Identity band
Pinned at the top of every patient context. Surname in capitals. Switching file reloads the band first; results never render under another patient's band.
Lifecycle stepper
7 fixed steps: received, aliquoted, on analyzer, results, technical, biological, released. Filled = done, ring = current, violet = held. Always paired with a text label of the current step.
Rule trace line
Rule id + version in mono, colored by outcome, then the human sentence. Every rule applied to a result is listed, passed ones included.
Demo banner
Permanent, above the shell, on every route including print and exports. Not dismissible. Amber is reserved for it.
Fields & controls
Label above in caps, 36 px controls, help linked to the control. Segmented controls are a radio group.
Dialog
The native <dialog>: focus kept inside by the browser. The critical call mode cancels Escape and offers no close button.
Stale value
An em dash, never a zero or an old value. Always the source and the age.
QC hold banner
Full width under the shell: the run, the violated rules, the number of held results and the unblock condition.
Virtualized list
1200 rows- 26110500000MOREAU, Lucie
- 26110500001GARNIER, Louis
- 26110500002PETIT, Jeanne
- 26110500003LEROY, Thomas
- 26110500004FAURE, Claire
- 26110500005BERNARD, Paul
- 26110500006ROUSSEAU, Anne-Marie
Fixed row height windowing: only the rows in view are in the DOM. Used for any list that can exceed 200 rows.
QC and trend charts (Exalus)
- Accepted
- Warning (contributes to rule)
- Rejection
- Pending rerun after corrective action
| Run | Date | Value (mmol/L) | SD | Status |
|---|---|---|---|---|
| R-0502 | 16/10/2026 | 4.02 | +0.2 | Accepted |
| R-0503 | 17/10/2026 | 3.96 | −0.5 | Accepted |
| R-0504 | 18/10/2026 | 4.06 | +0.7 | Accepted |
| R-0505 | 20/10/2026 | 3.91 | −1.1 | Accepted |
| R-0506 | 21/10/2026 | 4.02 | +0.2 | Accepted |
| R-0507 | 22/10/2026 | 4.05 | +0.6 | Accepted |
| R-0508 | 23/10/2026 | 3.98 | −0.3 | Accepted |
| R-0509 | 24/10/2026 | 4.10 | +1.2 | Accepted |
| R-0510 | 26/10/2026 | 4.03 | +0.4 | Accepted |
| R-0511 | 27/10/2026 | 3.94 | −0.8 | Accepted |
| R-0512 | 28/10/2026 | 4.04 | +0.5 | Accepted |
| R-0513 | 29/10/2026 | 4.11 | +1.4 | Warning (contributes to rule) |
| R-0514 | 30/10/2026 | 4.07 | +0.9 | Accepted |
| R-0515 | 01/11/2026 | 4.13 | +1.6 | Warning (contributes to rule) |
| R-0516 | 02/11/2026 | 4.10 | +1.2 | Warning (contributes to rule) |
| R-0517 | 03/11/2026 | 4.17 | +2.1 | Rejection |
| R-0518 | 04/11/2026 | 4.19 | +2.4 | Rejection |
| R-0519 | 05/11/2026 | 4.02 | +0.2 | Pending rerun after corrective action |
| Date | Value (mmol/L) | Flag |
|---|---|---|
| 12/10/2026 | 4.3 | None |
| 20/10/2026 | 4.4 | None |
| 28/10/2026 | 4.9 | None |
| 03/11/2026 | 4.6 | None |
| 05/11/2026 | 6.8 | HH |
Levey-Jennings in SD units with ±1 SD solid, ±2 / ±3 SD dashed; the analyte trend on a time axis to scale with the reference band and the critical limit.
7 · Safety patterns
Blocked release
The unblocking action sits directly above the blocked one.
Amended result
Released results are immutable. The original stays visible, struck through, with its version.
Stale or missing data
An em dash, never a zero or an old value. Always the source and the age.
Identity mismatch
Hard stop. No override button; resolution goes through a non-conformity record.
8 · Writing & i18n
English is the default; French is a full translation. French labels use the infinitive, never tu or vous. Verbs on actions, nouns on states. Read from the live catalogs.
| Key | English | Français |
|---|---|---|
| action.validate | Validate | Valider |
| action.signRelease | Sign & release | Signer et diffuser |
| action.requestRerun | Request rerun | Demander un repassage |
| action.documentCall | Document critical value call | Documenter l'appel de valeur critique |
| action.recordCorrective | Record action & launch QC rerun | Enregistrer l'action et relancer le CIQ |
| nc.recollect | Re-collect | Faire reprélever |
| nc.acceptComment | Accept with comment | Accepter avec commentaire |
| state.held | QC held | Bloqué par le CIQ |
| state.amended | Amended | Rectifié |
9 · Tokens (code)
Single source in styles/tokens/probatio.css, exposed to Tailwind through @theme. Components consume tokens only. Values read live from the stylesheet.
:root {
}10 · Rules for implementers
Do
- Read colors, spacing and type from --pb-* tokens only.
- Render results through the one ResultRow component; it refuses to render without unit, range and analyzer.
- Derive flags (L/H/LL/HH) and statuses from the rules engine output, never recompute them in the UI.
- Show the rule id and version wherever a rule decided something.
- Give every blocked action a reason string and a link to the unblocking step.
- Write each label once per language in the i18n catalog, French in the infinitive.
- Virtualize any list that can exceed 200 rows (validation queue, tracking).
- Keep the demo banner in the root layout so no route can drop it.
Don't
- Use a status color for decoration, branding or charts unrelated to that status.
- Show a value from cache as if it were current; mark it stale with its age.
- Put release, call or reject behind a keyboard shortcut or a row double-click.
- Edit a released result in place; open an amended report instead.
- Add gradients, shadows deeper than 1 px, emoji or illustrations.
- Abbreviate units or invent ones; units come from the analyte configuration.
- Add a dependency for a component that this page already specifies.
- Hide QC holds behind a filter that is on by default.
QC charts (Levey-Jennings, trends) are built with Exalus and take their colors from these tokens: mean in text.secondary, ±1 SD in line.strong, ±2 SD warning, ±3 SD critical.