|Design System

Core Component

Avatar

User representation with image, initials fallback, and optional status indicator.

Preview

Source

Full component implementation using the design system tokens.

tsx
"use client";

import { useState } from "react";
import { User } from "lucide-react";

const sizeMap = {
  sm: { container: "w-8 h-8", text: "text-xs", icon: "w-4 h-4", status: "w-2.5 h-2.5 -bottom-0 -right-0" },
  md: { container: "w-10 h-10", text: "text-sm", icon: "w-5 h-5", status: "w-3 h-3 -bottom-0.5 -right-0.5" },
  lg: { container: "w-12 h-12", text: "text-base", icon: "w-6 h-6", status: "w-3.5 h-3.5 -bottom-0.5 -right-0.5" },
};

const statusColors = {
  online: "bg-green-500",
  offline: "bg-overlay/20",
  busy: "bg-red-500",
  away: "bg-amber-500",
};

function getInitials(name: string): string {
  return name.split(" ").map(w => w[0]).filter(Boolean).slice(0, 2).join("").toUpperCase();
}

export function DSAvatar({
  src, alt, name, size = "md", status,
}: {
  src?: string; alt?: string; name?: string;
  size?: "sm" | "md" | "lg";
  status?: "online" | "offline" | "busy" | "away";
}) {
  const [imgError, setImgError] = useState(false);
  const styles = sizeMap[size];
  const showImage = src && !imgError;
  const initials = name ? getInitials(name) : null;

  return (
    <div className="relative inline-flex" role="img" aria-label={alt || name || "Avatar"}>
      <div className={`${styles.container} rounded-full overflow-hidden flex items-center justify-center bg-surface border border-overlay/10`}>
        {showImage ? (
          <img src={src} alt={alt || name || "Avatar"} className="w-full h-full object-cover" onError={() => setImgError(true)} />
        ) : initials ? (
          <span className={`${styles.text} font-medium text-foreground select-none`}>{initials}</span>
        ) : (
          <User className={`${styles.icon} text-tertiary`} />
        )}
      </div>
      {status && <span className={`absolute ${styles.status} ${statusColors[status]} rounded-full border-2 border-background`} />}
    </div>
  );
}

Props

All available props with types and defaults.

PropTypeDescription
srcstringImage URL
altstringAlt text for the image
namestringUser name for initials fallback
size'sm' | 'md' | 'lg'Avatar size
status'online' | 'offline' | 'busy' | 'away'Status indicator dot

Variants

With Image

Avatar displaying a user photo.

tsx
<DSAvatar src="/avatar.jpg" name="Jane Doe" />

Initials Fallback

Shows initials when no image is provided.

tsx
<DSAvatar name="John Smith" />

With Status

Status indicator dot at the bottom-right corner.

tsx
<DSAvatar name="Alice" status="online" />

Sizes

Three size options for different contexts.

tsx
<DSAvatar name="A" size="sm" />
<DSAvatar name="AB" size="md" />
<DSAvatar name="ABC" size="lg" />

Prompt Guide

Prompt Guide — Avatar

Use for

  • User profile pictures in chat threads
  • Participant lists in conversations
  • Account menus and settings
  • Assignee indicators on tasks

Don't use for

  • Generic icons — avatar implies a person
  • Logo display — use an image component
  • Large hero images — avatar is for compact contexts

AI Context

Fallback chain: image → initials → User icon. The initials are derived from the name prop (first letter of each word, max 2). Status dot uses absolute positioning with a border matching the background for the cutout effect.