Skip to content

Patient banner

Who the screen is about, at the top of every clinical view: name, date of birth and age, sex, identifiers, alerts and allergies, laid out as the NHS patient banner standard sets them, so the right patient is never in doubt.

OKAFOR, Grace Adaeze (Mrs)

Falls risk
Born
12-Jan-1958 (68 years)
Sex
Female
NHS number
999 654 3218
Hospital number
RX4 118204
Allergies: Penicillin (anaphylaxis), Latex

Installation

In a project set up as in Installation, run:

bunx shadcn@4.22.1 add https://organui.com/r/patient-banner.json

Or by name: bunx shadcn@4.22.1 add @organui/patient-banner.

The source installs into your UI components directory, along with shadcn's badge if you do not have it yet. It holds no state, so it renders in server and client components alike.

View registry item JSON

Usage

import {
  formatNhsNumber,
  PatientBanner,
} from "@/components/ui/patient-banner"

export function Header() {
  return (
    <PatientBanner
      patient={{
        name: { family: "Okafor", given: ["Grace", "Adaeze"], prefix: "Mrs" },
        birthDate: "1958-01-12",
        sex: "Female",
        identifiers: [
          { label: "NHS number", value: formatNhsNumber("9996543218") },
        ],
      }}
      allergies={["Penicillin (anaphylaxis)", "Latex"]}
      alerts={["Falls risk"]}
    />
  )
}

Identity

The name reads family name first, in capitals, then the given names and the title in brackets: OKAFOR, Grace Adaeze (Mrs). Capitals set the family name apart, so two patients with the same given name are not confused. formatPatientName gives the same text for a list or a heading of your own.

Dates show as 12-Jan-1958, day, month and year in a form no reader can swap, and in UTC, so the server and client render the same text. Pass formatDate to use another form. Age follows the date of birth: in days under four weeks, in months under two years, then in completed years. It is counted on today, which defaults to the current date. A deceasedDate replaces the age with the date of death.

Identifiers show in the order you pass them, the primary one first, each with its own label. formatNhsNumber spaces an NHS number in groups of three, three and four, and isValidNhsNumber checks its modulus 11 check digit before you show it.

Allergies and alerts

Allergies have three states, and each reads differently. Leave allergies out, or pass an empty list, when they have not been recorded: the banner says so with a question icon, because not asking is not the same as none. Pass "none-known" once no known allergies has been recorded, and the list of substances otherwise, which shows in bold with a warning icon.

alerts are the warnings to see before anything else, such as "DNACPR" or "Safeguarding", as badges beside the name. None of these depends on color alone, and the banner uses no red, which lab results keep for critical values.

Layout

The banner is a section named for the patient, with the name as its heading and the details in a description list. It sizes to its container, and the details wrap onto more lines on a phone rather than scrolling sideways.

A display component. It does not look up, match or verify patients; the examples are fictional, with NHS numbers from the 999 range the NHS keeps for testing.

Examples

Allergy States

Not recorded, no known allergies, and a recorded allergy each read differently.

BRENNAN, Tom (Mr)

Born
03-Jun-1979 (47 years)
Sex
Male
Allergies not recorded

HADDAD, Leila (Ms)

Born
20-Nov-1991 (34 years)
Sex
Female
No known allergies

OSEI, Kwame (Mr)

Born
08-Feb-1947 (79 years)
Sex
Male
Allergies: Codeine (vomiting)

A Baby

Age in months under two years, and in days under four weeks, with an alert.

NOVAK, Ella

Safeguarding
Born
19-Jan-2026 (9 months)
Sex
Female
NHS number
999 100 2014
No known allergies

API Reference

Import PatientBannerProps from the same file as PatientBanner.

PatientBanner props
PropTypeDefault
patientPatient

Name, date of birth, sex, identifiers and any date of death.

Required
allergiesPatientAllergies

Substances, `"none-known"`, or nothing when not recorded.

—
alertsreadonly string[]

Warnings to see before anything else, such as "DNACPR" or "Safeguarding".

[]
todayDate

The day age is counted on. Defaults to today.

—
formatDate(date: string) => string

Defaults to an unambiguous UTC date such as "12-Jan-1958".

formatBannerDate

Any other prop, such as className, id or aria-*, is passed to the root <section>.