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.
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
| State | Signalled by | Duration | Announced as |
|---|---|---|---|
| default | — | — | Role and name |
| hover | Brightness shift only | --njt-dur-1 80 ms |
Nothing — hover is not a state on touch and carries no information |
| focus-visible | 2 px --ring outline, 2 px offset |
Instant, no transition | Focus move |
| pressed | Scale 0.98 + darkening | --njt-dur-1 |
aria-pressed where it is a toggle |
| selected | --accent fill + 2 px border |
--njt-dur-2 140 ms | aria-selected / aria-current |
| pending | Spinner + label change; input blocked | Until resolved | aria-busy="true" + live region |
| read-only | --muted fill, full-contrast text |
— | readonly — value is selectable and copyable |
| disabled | 50 % opacity, no pointer events | — | disabled + adjacent text stating the precondition |
| error | 2 px --destructive border + message |
On blur | aria-invalid + aria-describedby |
Focus is governed
--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.
:focus-visible, not:focus— so pointer users do not see a ring on every click while keyboard users always do.- Offset by 2 px so the ring is legible against both the control and the surface behind it.
- Focus order follows DOM order, always. Never reorder visually with CSS.
- Arriving content never steals focus — not a new alarm, not a queue update, not a completed background task. See Alert Banner.
- Focus returns to its trigger when a dialog or popover closes.
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.
| State | Means | Requirement |
|---|---|---|
| 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. |
Available once you have opened and assessed the ECG.
The precondition is stated where the clinician is already looking.
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
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.
| 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
- Hover and press: 80 ms. Fast enough to feel like the control responded, short enough not to lag a rapid sequence.
- Colour and selection: 140 ms.
- Focus: no transition. An animated focus ring is a focus ring you can outrun with the tab key.
- Never animate a state on re-render. A list that re-flashes every poll trains clinicians to ignore movement — the same attention budget alarms depend on.
- Under
prefers-reduced-motion, states change instantly. They never stop changing.
Outcomes of use
What this contributes to, in the terms of Usability & context of use.
- Effectiveness — the control the clinician believes is focused, selected or pending is the one that actually is. Mis-activation is the failure this foundation prevents.
- Efficiency — state feedback within 80 ms removes the hesitation and the second press that an unresponsive-feeling control provokes.
- Satisfaction — perceived responsiveness and perceived control. An interface that never quite confirms it heard you is experienced as untrustworthy long before anyone can say why.
Do's and don'ts
A 2 px ring, offset, legible against both the control and the surface behind it.
outline: none replaced by a slightly darker fill. A keyboard or switch user cannot tell where focus is.
Read-only at full text contrast. It is a real value the clinician may read and copy.
Read-only dimmed like a disabled control. A present fact now reads as unavailable.
Clinical safety notes
Trace these in your risk file (ISO 14971) and usability engineering file (IEC 62366-1).
- Focus always visible, governed at ≥ 3:1. Mitigates: activating the wrong control when operating by keyboard, switch or voice.
- Nothing revealed only on hover. Mitigates: information that is simply absent on touch surfaces — units, identifiers, confidence scores.
- Pending blocks re-submission. Mitigates: duplicate irreversible actions such as two cath-lab activations.
- Disabled always explains itself. Mitigates: a clinician abandoning the tool mid-workflow because a control is dead for unknown reasons.
- Read-only never dimmed. Mitigates: a real clinical value being read as unavailable.
- States never use alarm hues. Mitigates: interaction feedback being read as clinical priority, and priority losing salience through competition.
- No animation on re-render. Mitigates: attentional habituation to movement, which alarms depend on.
Related
- Tokens — why
--ringand--inputare governed. - Accessibility — focus, target size and forced-colours modes.
- Colour — the separation between state and signal.
- Button · Text field — these states applied.