Presence Avatar
Show presence and unread messages on a Blobz avatar.
View codeHide code
import { DEMO_PEOPLE, getFirstName } from "@/lib/demo-people";
import {
PresenceAvatar,
type PresenceStatus,
} from "@/components/blobz/presence-avatar";
const PEOPLE = [
{
name: DEMO_PEOPLE.janakiAmmal,
palette: ["#dff4ff", "#38bdf8"],
status: "online",
},
{
name: DEMO_PEOPLE.vikramSarabhai,
palette: ["#f4e8ff", "#b881eb"],
status: "online",
unreadCount: 3,
},
{
name: DEMO_PEOPLE.srinivasaRamanujan,
palette: ["#fff1df", "#f48a61"],
status: "away",
},
{
name: DEMO_PEOPLE.gagandeepKang,
palette: ["#e8edff", "#a7a8f4"],
status: "offline",
unreadCount: 128,
},
] as const satisfies readonly {
name: string;
palette: readonly [string, string];
status: PresenceStatus;
unreadCount?: number;
}[];
export function PresenceAvatarExample() {
return (
<div className="grid w-full max-w-xl grid-cols-2 justify-items-center gap-9 sm:grid-cols-4">
{PEOPLE.map((person) => (
<div
className="flex flex-col items-center gap-5 text-center"
key={person.name}
>
<PresenceAvatar
avatar={{
alt: `${person.name} avatar`,
frame: "circle",
name: getFirstName(person.name),
palette: person.palette,
}}
status={person.status}
unreadCount={"unreadCount" in person ? person.unreadCount : 0}
/>
<span className="text-muted-foreground text-xs">
{person.status}
{"unreadCount" in person ? `, ${person.unreadCount} unread` : ""}
</span>
</div>
))}
</div>
);
}Installation
Register the Blobz registry once in your project, then install:
npx shadcn@latest add @blobz/presence-avatarThe base avatar is installed automatically.
Usage
import { PresenceAvatar } from "@/components/blobz/presence-avatar";
<PresenceAvatar
avatar={{ alt: "Janaki Ammal avatar", name: "Janaki", frame: "circle" }}
status="online"
unreadCount={3}
/>The status prop accepts online, away, and offline. Unread counts above 99 display as 99+. Presence and unread counts include accessible labels.