Foundations

Interaction states

What a control looks like as a clinician moves through it — and the rules that stop those appearances being confused with each other, or with clinical priority.

Stable · v1.0 WCAG 2.2 AA SC 1.4.11 · 2.4.13

Overview

Interaction state is the smallest thing in a design system and one of the easiest to get dangerously wrong. Two failures recur in clinical software: a state that cannot be seen at all — focus removed for aesthetics — and a state that is too visible, borrowing the colour vocabulary that alarm priority owns.

This system therefore treats interaction feedback as a strictly separate visual language from clinical signal. States use surface, border and elevation. Priority uses the IEC hues. They never trade vocabulary.

Consistent

A state looks the same on every control, everywhere. A clinician should never have to learn what "selected" means twice in one product.

Distinct

No two states are confusable with each other, and none is confusable with a priority signal. Selected is not pressed; pressed is not disabled; nothing interactive is red.

Always perceivable

Every state is visible without hovering, at 3:1 against its surroundings, and carried by more than colour. Focus is never removed — under any circumstance.

The state set

All states · primary and outline
default
hover
focus-visible
pressed
selected
pending
read-only
disabled
StateSignalled byDurationAnnounced as
defaultRole and name
hoverBrightness shift only--njt-dur-1 80 ms Nothing — hover is not a state on touch and carries no information
focus-visible2 px --ring outline, 2 px offset Instant, no transitionFocus move
pressedScale 0.98 + darkening--njt-dur-1 aria-pressed where it is a toggle
selected--accent fill + 2 px border --njt-dur-2 140 msaria-selected / aria-current
pendingSpinner + label change; input blocked Until resolvedaria-busy="true" + live region
read-only--muted fill, full-contrast text readonly — value is selectable and copyable
disabled50 % opacity, no pointer events disabled + adjacent text stating the precondition
error2 px --destructive border + message On bluraria-invalid + aria-describedby

Focus is governed

Governed — never removable

--ring is a governed token, gated in CI at ≥ 3:1 against background, card and muted surfaces in both themes. outline: none without an equivalent replacement fails review — not because it is untidy, but because a clinician operating by keyboard, switch or voice with no visible focus is activating controls blind. That is a use error the interface caused.

Hover carries nothing

Roughly half the surfaces this system targets are touch-only, where hover does not exist — and on the rest a clinician may be operating by keyboard with gloved or occupied hands. No information, control or affordance may be revealed only on hover. That includes tooltips carrying units, truncated identifiers, confidence scores and row actions. Hover may make something easier to see. It may never be the only way to see it.

Disabled, read-only and pending

Three states that look similar and mean entirely different things. Confusing them produces the most common dead end in clinical software: a control the clinician cannot use and cannot find out why.

StateMeansRequirement
read-only A real value the clinician may read and copy but not change — model version, acquisition time, an MRN. Full text contrast. Selectable. Never dimmed — it is information, not an absence.
disabled An action that is not currently applicable. Always paired with adjacent text saying what would make it applicable. A disabled control with no explanation is a defect.
pending An action has been accepted and is in flight. Blocks re-submission. Announces. Never a full-screen overlay that hides an alarm.
Do

Available once you have opened and assessed the ECG.

The precondition is stated where the clinician is already looking.

Don't

Unexplained. Under time pressure this reads as a broken product, and the clinician reaches for the phone instead.

Prefer explaining to disabling. Where a precondition is unmet, keeping the control enabled and explaining on activation is usually safer than a dead control — the clinician learns the rule instead of guessing at it.

States never borrow alarm colour

The separation rule

Interaction states use surface, border, elevation and opacity. Clinical priority uses the IEC hues. A selected row is filled with --accent, never with a priority colour. A hovered row lightens, never reddens. --destructive is the single exception and is confined to the error state and destructive controls, where it means "this destroys data" — never "this patient is deteriorating". See Colour.

Selection over priority — both legible, neither confused
Priority indicator Patient Finding
HARLAND, A.STEMI pattern — anterior V2–V4
OKONKWO, B.hs-troponin rising

The selected row carries an --accent fill; its priority is still stated by the rail and by the word in the row. Selection and priority read independently.

Timing

Outcomes of use

What this contributes to, in the terms of Usability & context of use.

Do's and don'ts

Do

A 2 px ring, offset, legible against both the control and the surface behind it.

Don't

outline: none replaced by a slightly darker fill. A keyboard or switch user cannot tell where focus is.

Do

Read-only at full text contrast. It is a real value the clinician may read and copy.

Don't

Read-only dimmed like a disabled control. A present fact now reads as unavailable.

Clinical safety notes

Risk controls carried by this foundation

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

NotJustAnyMed.Tech Design System · Interaction states · v1.0 · draft for review