implement
Avatar

Avatar

A user's photo, with initials to fall back on.

AB
ER
AB
GH
CN
import { Div } from "@implementjs/core";
import { Avatar, AvatarFallback, AvatarImage } from "@/lib/components/ui/avatar";

export default function AvatarDemo() {
	return Div(
		{ class: "flex flex-row flex-wrap items-center gap-8" },
		Avatar(
			AvatarImage({ src: "https://github.com/ieedan.png", alt: "@ieedan" }),
			AvatarFallback("AB"),
		),
		Avatar(
			AvatarImage({ src: "https://github.com/broken-link-404.png/nope", alt: "broken" }),
			AvatarFallback("ER"),
		),
		Div(
			{
				class:
					"flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background *:data-[slot=avatar]:grayscale",
			},
			Avatar(
				AvatarImage({ src: "https://github.com/ieedan.png", alt: "@ieedan" }),
				AvatarFallback("AB"),
			),
			Avatar(
				AvatarImage({ src: "https://github.com/github.png", alt: "@github" }),
				AvatarFallback("GH"),
			),
			Avatar(
				AvatarImage({ src: "https://github.com/shadcn.png", alt: "@shadcn" }),
				AvatarFallback("CN"),
			),
		),
	);
}

Installation

npx jsrepo add @implementjs/ui/avatar

Nothing else comes with it — this one stands alone on @implementjs/core and @implementjs/primitives.

Usage

Avatar is a 2rem circle that clips whatever is inside it. AvatarImage fills it, and AvatarFallback takes over when the image is still loading or has failed — the primitive tracks the load, so there is no flash of initials behind a photo that arrives.

import { Avatar, AvatarFallback, AvatarImage } from "@/lib/components/ui/avatar";

Avatar(AvatarImage({ src: "https://github.com/ieedan.png", alt: "@ieedan" }), AvatarFallback("AB"));

Sizing and stacking

Size is a class on the root, and the parts follow it:

Avatar({ class: "size-12" }, AvatarImage({ src, alt: "" }), AvatarFallback("AB"));

For an overlapping row, give the group a negative gap and ring each avatar in the page background so the edges stay readable:

Div(
	{ class: "flex -space-x-2" },
	Avatar({ class: "ring-2 ring-background" }, AvatarFallback("AB")),
	Avatar({ class: "ring-2 ring-background" }, AvatarFallback("CD")),
);

API Reference

Every prop the styling does not consume is forwarded to the Avatar primitive, so the tables below are the whole surface — the behavior props and the styling ones together.

Avatar

The root. Tracks the image's loading status for the parts inside it. Styled as a 2rem circle that clips whatever is inside it. Renders a Div; extra props are forwarded onto it.

PropTypeDefaultDescription
delayMsnumber0How long to wait after the image loads before showing it, preventing a flash on fast connections.
onLoadingStatusChange(status: AvatarLoadingStatus) => voidCalled whenever the loading status changes.
Data attributeValue
[data-avatar-root]Present
[data-status]"loading" | "loaded" | "error"

AvatarImage

The picture. Preloaded off-DOM and only shown once loaded; a reactive src re-runs the load. Renders a Img; extra props are forwarded onto it.

Data attributeValue
[data-avatar-image]Present
[data-status]"loading" | "loaded" | "error"

AvatarFallback

Shown until the image has loaded — initials, an icon, anything. Styled as a filled circle that centers its content. Renders a Span; extra props are forwarded onto it.

Data attributeValue
[data-avatar-fallback]Present
[data-status]"loading" | "loaded" | "error"