Patient Info Card

Profile card with avatar and label/value detail rows.

Profile

Avatar with label/value detail rows.

M

Mertcan Esmergül

Date of Birth
28 July, 1997
Gender
Male
Blood Type
A rh+
GP Doctor
Mattheus Clarkson
function PatientInfoDemo() {
  return <PatientInfoCard name={PATIENT_NAME} initials={PATIENT_INITIALS} details={PATIENT_DETAILS} />;
}
function PatientInfoDemo() {
  return <PatientInfoCard name={PATIENT_NAME} initials={PATIENT_INITIALS} details={PATIENT_DETAILS} />;
}

Installation

npx shadcn@latest add https://boardcn.dev/r/patient-info-card.json
npx shadcn@latest add https://boardcn.dev/r/patient-info-card.json

npm packages

  • @remixicon/react

BoardCN dependencies

The CLI installs these for you — you do not need to add them yourself.

Source

The file the CLI copies into your project.

components/blocks/medical/patient-info-card.tsx
import { RiAddLine } from "@remixicon/react";
import type { ComponentType } from "react";
import { Avatar } from "@/components/base/avatar/avatar";
import { Button } from "@/components/base/buttons/button";
import { cx } from "@/utils/cx";

type IconComponent = ComponentType<{ className?: string; "aria-hidden"?: boolean | "true" | "false" }>;

export type PatientDetail = { icon: IconComponent; label: string; value: string };

export type PatientInfoCardProps = {
  name: string;
  initials: string;
  details: readonly PatientDetail[];
  className?: string;
};

export function PatientInfoCard({ name, initials, details, className }: PatientInfoCardProps) {
  return (
    <section
      className={cx(
        "flex h-[330px] w-full min-w-0 flex-col items-center gap-[15px] rounded-[20px] bg-background-secondary-default px-2.5 pt-6 pb-2.5",
        className,
      )}
    >
      <div className="relative">
        <Avatar size="lg" initials={initials} className="size-[66px] text-[24.75px]" />
        <Button
          variant="secondary"
          size="xs"
          iconOnly
          leadingIcon={RiAddLine}
          aria-label="Add profile photo"
          className="absolute -top-0.5 -right-0.5 rounded-full"
        />
      </div>
      <p className="text-title-2-medium whitespace-nowrap text-text-primary">{name}</p>
      <div className="flex w-full flex-1 flex-col gap-2.5">
        {details.map((detail) => (
          <div
            key={detail.label}
            className="flex w-full items-center justify-between rounded-2lg bg-background-inner-default px-2.5 py-2"
          >
            <div className="flex items-center gap-1.5">
              <detail.icon className="size-4 shrink-0 text-text-secondary" aria-hidden />
              <span className="text-body-regular whitespace-nowrap text-text-secondary">
                {detail.label}
              </span>
            </div>
            <span className="text-body-medium whitespace-nowrap text-text-primary">{detail.value}</span>
          </div>
        ))}
      </div>
    </section>
  );
}
import { RiAddLine } from "@remixicon/react";
import type { ComponentType } from "react";
import { Avatar } from "@/components/base/avatar/avatar";
import { Button } from "@/components/base/buttons/button";
import { cx } from "@/utils/cx";

type IconComponent = ComponentType<{ className?: string; "aria-hidden"?: boolean | "true" | "false" }>;

export type PatientDetail = { icon: IconComponent; label: string; value: string };

export type PatientInfoCardProps = {
  name: string;
  initials: string;
  details: readonly PatientDetail[];
  className?: string;
};

export function PatientInfoCard({ name, initials, details, className }: PatientInfoCardProps) {
  return (
    <section
      className={cx(
        "flex h-[330px] w-full min-w-0 flex-col items-center gap-[15px] rounded-[20px] bg-background-secondary-default px-2.5 pt-6 pb-2.5",
        className,
      )}
    >
      <div className="relative">
        <Avatar size="lg" initials={initials} className="size-[66px] text-[24.75px]" />
        <Button
          variant="secondary"
          size="xs"
          iconOnly
          leadingIcon={RiAddLine}
          aria-label="Add profile photo"
          className="absolute -top-0.5 -right-0.5 rounded-full"
        />
      </div>
      <p className="text-title-2-medium whitespace-nowrap text-text-primary">{name}</p>
      <div className="flex w-full flex-1 flex-col gap-2.5">
        {details.map((detail) => (
          <div
            key={detail.label}
            className="flex w-full items-center justify-between rounded-2lg bg-background-inner-default px-2.5 py-2"
          >
            <div className="flex items-center gap-1.5">
              <detail.icon className="size-4 shrink-0 text-text-secondary" aria-hidden />
              <span className="text-body-regular whitespace-nowrap text-text-secondary">
                {detail.label}
              </span>
            </div>
            <span className="text-body-medium whitespace-nowrap text-text-primary">{detail.value}</span>
          </div>
        ))}
      </div>
    </section>
  );
}

Props

Generated from the component's TypeScript types. Standard DOM and React Aria props are omitted.

PatientInfoCard

PropTypeDefaultDescription
detailsrequiredreadonly PatientDetail[]
initialsrequiredstring
namerequiredstring
classNamestring