Presence Indicator

Shows online/availability status.

html

<span class="presence presence--online">
  <svg class="presence__glyph" width="10" height="10" viewBox="0 0 10 10" role="img" aria-label="Priya Nair is">
    <circle cx="5" cy="5" r="4.5"/>
    <path class="presence__mark" d="M2.5 5l1.7 1.7L7.5 3"/>
  </svg>
  <span class="presence__label"></span>
</span>
<style>
.presence { display: inline-flex; align-items: center; gap: 6px; font: 13px/1.3 system-ui, sans-serif; color: #241430; }
.presence__glyph circle { stroke: #FAF7F2; stroke-width: 1; }
.presence__mark { fill: none; stroke: #FAF7F2; stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; display: none; }
.presence--online circle { fill: #2f8f4e; }
.presence--away circle { fill: #E8A020; }
.presence--busy circle { fill: #b3261e; }
.presence--busy .presence__mark { display: block; d: path("M2.5 5h5"); }
.presence--offline circle { fill: none; stroke: #24143055; stroke-width: 1.2; }
.presence--online .presence__mark { display: block; }
.presence--away .presence__mark, .presence--offline .presence__mark { display: none; }
.presence--online .presence__label::before { content: "Online"; }
.presence--away .presence__label::before { content: "Away"; }
.presence--busy .presence__label::before { content: "Busy"; }
.presence--offline .presence__label::before { content: "Offline"; }
</style>

tailwind

<span class="presence-tw presence-tw--online inline-flex items-center gap-1.5 font-sans text-[13px] text-[#241430]">
  <svg class="presence-tw__glyph" width="10" height="10" viewBox="0 0 10 10" role="img" aria-label="Priya Nair is">
    <circle cx="5" cy="5" r="4.5"/>
    <path class="presence-tw__mark" d="M2.5 5l1.7 1.7L7.5 3"/>
  </svg>
  <span class="presence-tw__label"></span>
</span>
<style>
.presence-tw__glyph circle { stroke: #FAF7F2; stroke-width: 1; }
.presence-tw__mark { fill: none; stroke: #FAF7F2; stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; display: none; }
.presence-tw--online .presence-tw__glyph circle { fill: #2f8f4e; }
.presence-tw--away .presence-tw__glyph circle { fill: #E8A020; }
.presence-tw--busy .presence-tw__glyph circle { fill: #b3261e; }
.presence-tw--offline .presence-tw__glyph circle { fill: none; stroke: #24143055; stroke-width: 1.2; }
.presence-tw--online .presence-tw__mark { display: block; }
.presence-tw--online .presence-tw__label::before { content: "Online"; }
.presence-tw--away .presence-tw__label::before { content: "Away"; }
.presence-tw--busy .presence-tw__label::before { content: "Busy"; }
.presence-tw--offline .presence-tw__label::before { content: "Offline"; }
</style>

react

export function PresenceIndicator({
  name = "Priya Nair",
  status = "online",
  showLabel = true,
  size = 10,
}) {
  const fill = { online: "#2f8f4e", away: "#E8A020", busy: "#b3261e", offline: "none" }[status] ?? "#2f8f4e";
  const label = { online: "Online", away: "Away", busy: "Busy", offline: "Offline" }[status] ?? "Online";
  return (
    <span style={{ display: "inline-flex", alignItems: "center", gap: 6, font: "13px/1.3 system-ui, sans-serif", color: "#241430" }}>
      <svg width={size} height={size} viewBox="0 0 10 10" role="img" aria-label={`${name} is ${label.toLowerCase()}`}>
        <circle cx="5" cy="5" r="4.5" fill={fill} stroke={status === "offline" ? "#24143055" : "#FAF7F2"} strokeWidth={status === "offline" ? 1.2 : 1} />
        {status === "online" && <path d="M2.5 5l1.7 1.7L7.5 3" fill="none" stroke="#FAF7F2" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" />}
        {status === "busy" && <path d="M2.5 5h5" fill="none" stroke="#FAF7F2" strokeWidth="1.4" strokeLinecap="round" />}
      </svg>
      {showLabel && <span>{label}</span>}
    </span>
  );
}