Components · Feedback & status

Alert Banner

A persistent, priority-ranked message that tells a clinician what has changed, how urgent it is, and what to do next — without taking over the screen.

Stable · v1.0 shadcn/ui IEC 60601-1-8 WCAG 2.2 AA
Reference application

AcuteLine is a fictional SaMD used as the worked example across this system. It ingests 12-lead and continuous ECG plus high-sensitivity troponin results and flags patients with suspected acute coronary syndrome (ACS) for clinician review. It is decision support: it never diagnoses, never triggers therapy, and every output is confirmed by a qualified clinician. All screens, copy and patient data are fabricated.

Overview

An Alert Banner occupies a fixed region of the layout and stays there until the underlying condition resolves or a clinician acts on it. It is the workhorse for communicating change in a SaMD: a new detection, a degraded input, a failed analysis, a completed action.

In AcuteLine it carries the moment that matters most — the transition from "ECG received" to "this patient may be having a STEMI." That transition has to survive a noisy resuscitation bay, a clinician looking at a different monitor, and a screen three metres away.

When to use

When not to use

Design principles

Unambiguous

Priority, patient and finding must be readable in one glance, from across the room, by someone mid-task. If a clinician has to read it twice, the banner has failed.

Proportionate

Visual force matches clinical consequence — never engagement value. Every banner promoted above its true priority spends attention the next real alarm will need.

Actionable

State the next step and put the control to take it inside the banner. An alert that reports a problem but leaves the clinician hunting has moved work, not removed it.

Anatomy

priority: critical · variant: docked
1 2 3 4 5 6 7
1Priority fill. Carries the IEC colour — the only element allowed to encode priority chromatically, always paired with 2 and 3.
2Priority glyph. Redundant non-colour encoding for colour-vision deficiency and greyscale output.
3Title. The finding in clinical language. One line, ≤ 60 characters, most specific term first.
4Provenance. Patient, acquisition time, model version, confidence. Required on every algorithm-derived alert.
5Occurrence count. Only when identical alerts coalesce. Never hides the most recent instance.
6Primary action. Goes to the evidence — never straight to an irreversible step.
7Acknowledge. Critical and Urgent only. Records who acknowledged and when.

Priority levels

Four priority levels plus one confirmation level. The first three map onto IEC 60601-1-8 alarm priorities and inherit that standard's mandated hues. These are not brand decisions and must not be re-themed — see Colour.

LevelIECMeansAcuteLine exampleToken
criticalHighImmediate response required STEMI pattern detected --alarm-critical
urgentMediumPrompt response required hs-troponin rising on 0/1 h algorithm --alarm-urgent
advisoryLowAwareness; can wait Lead V3 signal quality degraded --alarm-advisory
infoNot an alarmState change, no response Analysis complete — no acute pattern --alarm-info
confirmationNot an alarmA clinician action succeeded Cath lab notified at 14:32 --alarm-ok
All five levels · variant: docked
Lead V3 signal quality degraded
Anterior interpretation may be limited. Re-apply the electrode and re-acquire.
HARLAND, A. · MRN 44812907 · 14:27:11
Analysis complete — no acute ischaemic pattern detected
A negative result does not exclude ACS. Continue clinical assessment.
VASQUEZ, R. · MRN 62907415 · 14:44:20 · model v4.2
Cath lab notified at 14:32
Sent by S. Whitfield · acknowledged by cath lab 14:33

Variants

docked

Full-bleed, solid fill, pinned beneath the patient header. The only variant permitted for critical. Use when the alert concerns the whole record in view.

inline

Scoped to a card or panel: surface drops to --card and priority moves to a 4 px rail. Use when the alert concerns one region — a single lead, one lab panel, one chart. The lower chroma is deliberate; an inline alert must not out-shout a docked one on the same screen.

variant: inline
Serial comparison unavailable
No prior ECG on file. Change from baseline cannot be assessed.
Paced rhythm detected
ST-segment criteria are not validated in ventricular pacing. Interpret with caution.

compact

Single line, no description or provenance. Permitted only inside dense repeating structures such as a triage worklist, and only when the full alert is one click away.

variant: compact · worklist rows
STEMI · anterior · HARLAND, A. · 14:26
Troponin rising · OKONKWO, B. · 14:41

States & behaviour

StateAppearanceRules
activeFull priority chroma Entry 220 ms ease-out. Never re-animate on re-render.
acknowledged (timed)Chroma drops to rail; countdown shown Returns to active automatically when the timer lapses if the condition persists.
acknowledged (indefinite)Chroma drops to rail Persists until resolved. Writes user and timestamp to the audit log.
audio-pausedVisually unchanged; separate audio indicator Pausing audio must never alter or hide the visual signal.
latchedFull chroma retained Condition resolved but was never seen. Stays until acknowledged.
resolvedRemoved, or replaced by a confirmation Critical alerts are never removed silently — always leave an event-log trace.
active → acknowledged
STEMI pattern detected — anterior leads V2–V4
acknowledged by S. Whitfield 14:27:04 · re-alerts in 09:12

Stacking and coalescence

Writing the message

Alert copy is a safety surface. Write for a reader who is interrupted, tired, reading at distance, and about to make a decision.

Do
STEMI pattern detected — anterior leads V2–V4
ST elevation 3.1 mm. Confirm ECG and activate local chest-pain pathway.

Names the finding, the territory and the measurement, then hands the decision back to the clinician.

Don't
Alert! AcuteLine has diagnosed a heart attack.
Please review the patient as soon as possible.

Claims a diagnosis the software is not cleared to make, leads with the product name, and gives no territory, measurement or action.

More do's and don'ts

Do
STEMI pattern detected — anterior leads V2–V4
HARLAND, A. · MRN 44 812 907 · 14:26:38 · model v4.2 · conf 0.94

Provenance on every algorithm-derived alert: who, when, which model, how sure.

Don't
STEMI pattern detected — anterior leads V2–V4

No patient, no time, no model version. Correct on the wrong record and nobody could tell.

Do
Lead V3 signal quality degraded
Re-apply the electrode and re-acquire.

A recoverable input problem, announced so the clinician knows the interpretation is limited.

Don't
Analysis complete

Silent about the degraded lead. The result looks as trustworthy as any other.

Accessibility

Measured contrast

FillForegroundRatioResult
--alarm-critical White5.64:1AA
--alarm-urgent Black12.49:1AAA
--alarm-advisory Black8.78:1AAA
--alarm-info Black10.98:1AAA
--alarm-ok White6.07:1AA

Critical and confirmation sit in the AA band, not AAA. Reaching 7:1 would darken the red past the point where it reads as an alarm hue, which IEC conformance depends on. The trade is deliberate and belongs in your accessibility conformance report.

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

These behaviours mitigate identified hazards and should be traced in your risk file (ISO 14971). Changing them is a design change with safety consequence, not a styling decision.

Usage do's and don'ts

Do
Lead V3 signal quality degraded
Anterior interpretation may be limited.

Match the level to the consequence. A recoverable input problem is advisory.

Don't
Lead V3 signal quality degraded
Anterior interpretation may be limited.

Inflating an electrode problem to critical trains clinicians to discount red — the definition of alarm fatigue.

Do
Analysis complete — no acute ischaemic pattern
A negative result does not exclude ACS. Continue clinical assessment.

State the limits of a negative result in the banner itself.

Don't
Patient is clear — no heart attack

Reads as an all-clear the software cannot give, and invites premature discharge.

Implementation

$ npx shadcn@latest add https://md.notjustany.tech/r/alert-banner.json

components/ui/alert-banner.tsx

import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"

const alertBannerVariants = cva(
  "relative flex w-full items-start gap-3 rounded-md border px-4 py-3 shadow-sm",
  {
    variants: {
      priority: {
        critical:     "bg-alarm-critical text-alarm-critical-foreground border-black/20",
        urgent:       "bg-alarm-urgent text-alarm-urgent-foreground border-black/20",
        advisory:     "bg-alarm-advisory text-alarm-advisory-foreground border-black/20",
        info:         "bg-alarm-info text-alarm-info-foreground border-black/15",
        confirmation: "bg-alarm-ok text-alarm-ok-foreground border-black/20",
      },
      variant: {
        docked:  "",
        inline:  "bg-card text-card-foreground border-border border-l-4 shadow-none",
        compact: "items-center gap-2 px-3 py-1.5",
      },
      state: {
        active:       "",
        acknowledged: "bg-card text-card-foreground border-border border-l-4 shadow-none",
      },
    },
    defaultVariants: { priority: "info", variant: "docked", state: "active" },
  }
)

// Safety invariants — enforced here so no product team has to remember them.
const ALARM_PRIORITIES = ["critical", "urgent"] as const

export interface AlertBannerProps
  extends React.HTMLAttributes<HTMLDivElement>,
    VariantProps<typeof alertBannerVariants> {
  /** Required when the alert is patient-specific. */
  subjectId?: string
  /** Required for algorithm-derived alerts. */
  modelVersion?: string
  /** 0–1. Rendered to two decimals; never abbreviated to a word. */
  confidence?: number
  observedAt?: string
  dismissible?: boolean
}

const AlertBanner = React.forwardRef<HTMLDivElement, AlertBannerProps>(
  ({ className, priority = "info", variant, state, dismissible, ...props }, ref) => {
    const isAlarm = ALARM_PRIORITIES.includes(priority as never)

    if (isAlarm && dismissible && process.env.NODE_ENV !== "production") {
      console.warn("[AlertBanner] `dismissible` ignored for alarm priorities.")
    }

    return (
      <div
        ref={ref}
        role={isAlarm ? "alert" : "status"}
        aria-live={isAlarm ? "assertive" : "polite"}
        data-priority={priority}
        className={cn(alertBannerVariants({ priority, variant, state }), className)}
        {...props}
      />
    )
  }
)
AlertBanner.displayName = "AlertBanner"

export { AlertBanner, alertBannerVariants }

Usage

<AlertBanner
  priority="critical"
  variant="docked"
  subjectId="44812907"
  observedAt="2026-08-13T14:26:38Z"
  modelVersion="4.2"
  confidence={0.94}
>
  <AlertBannerTitle>STEMI pattern detected — anterior leads V2–V4</AlertBannerTitle>
  <AlertBannerDescription>
    ST elevation 3.1 mm. Confirm ECG and activate local chest-pain pathway.
  </AlertBannerDescription>
  <AlertBannerActions>
    <Button size="sm" variant="secondary">Open ECG</Button>
    <AcknowledgeButton reassertAfter="PT10M" />
  </AlertBannerActions>
</AlertBanner>

Props

PropTypeDefaultNotes
priority critical | urgent | advisory | info | confirmation infoSets colour, glyph and ARIA role together. Not independently overridable.
variantdocked | inline | compact dockedcompact is rejected at critical outside a worklist.
stateactive | acknowledgedactive Acknowledged drops chroma but never text.
subjectIdstring Required for patient-specific alerts.
modelVersionstring Required for algorithm-derived alerts.
confidencenumber 0–1 Rendered to two decimals; never abbreviated to a word such as "high".
dismissiblebooleanfalse Ignored at critical and urgent; warns in development.

Events

NotJustAnyMed.Tech Design System · Alert Banner · v1.0 · draft for review
Reference applications named in this system are fictional; all patient data shown is fabricated.